From 18e08a55292a57b988df7fa14af2b4dd282a6486 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 11 Nov 2009 14:59:56 +0200 Subject: pci: pci.h cleanup: move out stuff not in pci.c pci.h declares some functions which aren't defined in pci.h. Clean up moving things to appropriate headers, and update all users. Signed-off-by: Michael S. Tsirkin --- hw/apb_pci.c | 1 + hw/apb_pci.h | 9 +++++++++ hw/lsi53c895a.c | 2 ++ hw/mips_malta.c | 2 ++ hw/pc.c | 5 +++++ hw/pci.h | 25 ------------------------- hw/ppc_newworld.c | 1 + hw/ppc_oldworld.c | 1 + hw/ppc_prep.c | 2 ++ hw/prep_pci.c | 1 + hw/prep_pci.h | 8 ++++++++ hw/r2d.c | 1 + hw/realview.c | 1 + hw/sh_pci.c | 1 + hw/sh_pci.h | 9 +++++++++ hw/sun4u.c | 1 + hw/usb-ohci.c | 1 + hw/usb-ohci.h | 9 +++++++++ hw/usb-uhci.c | 1 + hw/usb-uhci.h | 9 +++++++++ hw/versatilepb.c | 1 + hw/vmware_vga.c | 1 + hw/vmware_vga.h | 9 +++++++++ 23 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 hw/apb_pci.h create mode 100644 hw/prep_pci.h create mode 100644 hw/sh_pci.h create mode 100644 hw/usb-ohci.h create mode 100644 hw/usb-uhci.h create mode 100644 hw/vmware_vga.h diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 39998791f..1748d8dc7 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -29,6 +29,7 @@ #include "sysbus.h" #include "pci.h" #include "pci_host.h" +#include "apb_pci.h" /* debug APB */ //#define DEBUG_APB diff --git a/hw/apb_pci.h b/hw/apb_pci.h new file mode 100644 index 000000000..8869f9d32 --- /dev/null +++ b/hw/apb_pci.h @@ -0,0 +1,9 @@ +#ifndef APB_PCI_H +#define APB_PCI_H + +#include "qemu-common.h" + +PCIBus *pci_apb_init(target_phys_addr_t special_base, + target_phys_addr_t mem_base, + qemu_irq *pic, PCIBus **bus2, PCIBus **bus3); +#endif diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 7e47fc9ab..8b8a80b89 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -31,6 +31,8 @@ do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__); exit(1);} while do { fprintf(stderr, "lsi_scsi: error: " fmt , ## __VA_ARGS__);} while (0) #endif +#define LSI_MAX_DEVS 7 + #define LSI_SCNTL0_TRG 0x01 #define LSI_SCNTL0_AAP 0x02 #define LSI_SCNTL0_EPC 0x08 diff --git a/hw/mips_malta.c b/hw/mips_malta.c index 76884570f..571d8ced1 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -32,6 +32,8 @@ #include "flash.h" #include "mips.h" #include "pci.h" +#include "usb-uhci.h" +#include "vmware_vga.h" #include "qemu-char.h" #include "sysemu.h" #include "audio/audio.h" diff --git a/hw/pc.c b/hw/pc.c index 7c791c413..97964b27e 100644 --- a/hw/pc.c +++ b/hw/pc.c @@ -25,6 +25,11 @@ #include "pc.h" #include "fdc.h" #include "pci.h" +#include "vmware_vga.h" +#include "usb-uhci.h" +#include "usb-ohci.h" +#include "prep_pci.h" +#include "apb_pci.h" #include "block.h" #include "sysemu.h" #include "audio/audio.h" diff --git a/hw/pci.h b/hw/pci.h index 9a56d0df6..560da5074 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -413,31 +413,6 @@ static inline uint32_t pci_config_size(PCIDevice *d) return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE; } -/* lsi53c895a.c */ -#define LSI_MAX_DEVS 7 - -/* vmware_vga.c */ -void pci_vmsvga_init(PCIBus *bus); - -/* usb-uhci.c */ -void usb_uhci_piix3_init(PCIBus *bus, int devfn); -void usb_uhci_piix4_init(PCIBus *bus, int devfn); - -/* usb-ohci.c */ -void usb_ohci_init_pci(struct PCIBus *bus, int devfn); - -/* prep_pci.c */ -PCIBus *pci_prep_init(qemu_irq *pic); - -/* apb_pci.c */ -PCIBus *pci_apb_init(target_phys_addr_t special_base, - target_phys_addr_t mem_base, - qemu_irq *pic, PCIBus **bus2, PCIBus **bus3); - -/* sh_pci.c */ -PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, - void *pic, int devfn_min, int nirq); - /* These are not pci specific. Should move into a separate header. * Only pci.c uses them, so keep them here for now. */ diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c index da868d302..7579ddd34 100644 --- a/hw/ppc_newworld.c +++ b/hw/ppc_newworld.c @@ -29,6 +29,7 @@ #include "nvram.h" #include "pc.h" #include "pci.h" +#include "usb-ohci.h" #include "net.h" #include "sysemu.h" #include "boards.h" diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c index 9b49a3dbd..32fd03a90 100644 --- a/hw/ppc_oldworld.c +++ b/hw/ppc_oldworld.c @@ -32,6 +32,7 @@ #include "net.h" #include "isa.h" #include "pci.h" +#include "usb-ohci.h" #include "boards.h" #include "fw_cfg.h" #include "escc.h" diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c index cd561e10c..eb758f2da 100644 --- a/hw/ppc_prep.c +++ b/hw/ppc_prep.c @@ -29,6 +29,8 @@ #include "sysemu.h" #include "isa.h" #include "pci.h" +#include "prep_pci.h" +#include "usb-ohci.h" #include "ppc.h" #include "boards.h" #include "qemu-log.h" diff --git a/hw/prep_pci.c b/hw/prep_pci.c index a338f81e1..80e20ac1a 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -25,6 +25,7 @@ #include "hw.h" #include "pci.h" #include "pci_host.h" +#include "prep_pci.h" typedef PCIHostState PREPPCIState; diff --git a/hw/prep_pci.h b/hw/prep_pci.h new file mode 100644 index 000000000..cd6851288 --- /dev/null +++ b/hw/prep_pci.h @@ -0,0 +1,8 @@ +#ifndef QEMU_PREP_PCI_H +#define QEMU_PREP_PCI_H + +#include "qemu-common.h" + +PCIBus *pci_prep_init(qemu_irq *pic); + +#endif diff --git a/hw/r2d.c b/hw/r2d.c index c074a6e9c..e4c02f05e 100644 --- a/hw/r2d.c +++ b/hw/r2d.c @@ -29,6 +29,7 @@ #include "sysemu.h" #include "boards.h" #include "pci.h" +#include "sh_pci.h" #include "net.h" #include "sh7750_regs.h" #include "ide.h" diff --git a/hw/realview.c b/hw/realview.c index f0b834734..3322c4fd5 100644 --- a/hw/realview.c +++ b/hw/realview.c @@ -12,6 +12,7 @@ #include "primecell.h" #include "devices.h" #include "pci.h" +#include "usb-ohci.h" #include "net.h" #include "sysemu.h" #include "boards.h" diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 4277b01c9..52dc02e1e 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -24,6 +24,7 @@ #include "hw.h" #include "sh.h" #include "pci.h" +#include "sh_pci.h" #include "bswap.h" typedef struct { diff --git a/hw/sh_pci.h b/hw/sh_pci.h new file mode 100644 index 000000000..b1a5ec37c --- /dev/null +++ b/hw/sh_pci.h @@ -0,0 +1,9 @@ +#ifndef QEMU_SH_PCI_H +#define QEMU_SH_PCI_H + +#include "qemu-common.h" + +PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq, + void *pic, int devfn_min, int nirq); + +#endif diff --git a/hw/sun4u.c b/hw/sun4u.c index 2189fa06a..a7a227bbe 100644 --- a/hw/sun4u.c +++ b/hw/sun4u.c @@ -23,6 +23,7 @@ */ #include "hw.h" #include "pci.h" +#include "apb_pci.h" #include "pc.h" #include "nvram.h" #include "fdc.h" diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c index 0f7f4de15..7ab3a9861 100644 --- a/hw/usb-ohci.c +++ b/hw/usb-ohci.c @@ -32,6 +32,7 @@ #include "pci.h" #include "pxa.h" #include "devices.h" +#include "usb-ohci.h" //#define DEBUG_OHCI /* Dump packet contents. */ diff --git a/hw/usb-ohci.h b/hw/usb-ohci.h new file mode 100644 index 000000000..eefcef360 --- /dev/null +++ b/hw/usb-ohci.h @@ -0,0 +1,9 @@ +#ifndef QEMU_USB_OHCI_H +#define QEMU_USB_OHCI_H + +#include "qemu-common.h" + +void usb_ohci_init_pci(struct PCIBus *bus, int devfn); + +#endif + diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 8babb0265..671916e05 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -29,6 +29,7 @@ #include "usb.h" #include "pci.h" #include "qemu-timer.h" +#include "usb-uhci.h" //#define DEBUG //#define DEBUG_DUMP_DATA diff --git a/hw/usb-uhci.h b/hw/usb-uhci.h new file mode 100644 index 000000000..911948edb --- /dev/null +++ b/hw/usb-uhci.h @@ -0,0 +1,9 @@ +#ifndef QEMU_USB_UHCI_H +#define QEMU_USB_UHCI_H + +#include "qemu-common.h" + +void usb_uhci_piix3_init(PCIBus *bus, int devfn); +void usb_uhci_piix4_init(PCIBus *bus, int devfn); + +#endif diff --git a/hw/versatilepb.c b/hw/versatilepb.c index 226c616ee..391f5b88c 100644 --- a/hw/versatilepb.c +++ b/hw/versatilepb.c @@ -14,6 +14,7 @@ #include "net.h" #include "sysemu.h" #include "pci.h" +#include "usb-ohci.h" #include "boards.h" /* Primary interrupt controller. */ diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 33e876e95..bb3410105 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -24,6 +24,7 @@ #include "hw.h" #include "console.h" #include "pci.h" +#include "vmware_vga.h" #define VERBOSE #undef DIRECT_VRAM diff --git a/hw/vmware_vga.h b/hw/vmware_vga.h new file mode 100644 index 000000000..2e0813c81 --- /dev/null +++ b/hw/vmware_vga.h @@ -0,0 +1,9 @@ +#ifndef QEMU_VMWARE_VGA_H +#define QEMU_VMWARE_VGA_H + +#include "qemu-common.h" + +/* vmware_vga.c */ +void pci_vmsvga_init(PCIBus *bus); + +#endif -- cgit v1.2.3 From f88d7509b444ffa289e5054b34bc6f4800f6b76d Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:29 +0900 Subject: pci: fix pci_info_device(). It printed wrong limit value of bridge. This patch fixes it. Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci.c b/hw/pci.c index 5b3461cd6..040fa767f 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -986,7 +986,7 @@ static void pci_info_device(PCIBus *bus, PCIDevice *d) base, limit); base = pci_bridge_get_base(d, PCI_BASE_ADDRESS_SPACE_MEMORY); - limit= pci_config_get_memory_base(d, PCI_BASE_ADDRESS_SPACE_MEMORY); + limit= pci_bridge_get_limit(d, PCI_BASE_ADDRESS_SPACE_MEMORY); monitor_printf(mon, " memory range [0x%08"PRIx64", 0x%08"PRIx64"]\n", base, limit); -- cgit v1.2.3 From b6243d991a4d073b2c8c16737fec9ee74274bfeb Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:30 +0900 Subject: pci: move pci_data_{read, write}() declaration from pci.h to pci_host.h Now pci host stuff has been moved from pci.[hc] to pci_host.[hc] so the declaration of pci_data_{read, write}() should be in pci_host.h This patch moves them from pci.h to pci_host.h for consistency. Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.h | 2 -- hw/pci_host.h | 3 +++ hw/sh_pci.c | 1 + hw/versatile_pci.c | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/hw/pci.h b/hw/pci.h index 560da5074..2f213524c 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -293,8 +293,6 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, const char *default_devaddr); PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, const char *default_devaddr); -void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len); -uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len); int pci_bus_num(PCIBus *s); void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d)); PCIBus *pci_find_host_bus(int domain); diff --git a/hw/pci_host.h b/hw/pci_host.h index e5e877f4c..7cfa69356 100644 --- a/hw/pci_host.h +++ b/hw/pci_host.h @@ -36,6 +36,9 @@ typedef struct { PCIBus *bus; } PCIHostState; +void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len); +uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len); + /* for mmio */ int pci_host_config_register_io_memory(PCIHostState *s); int pci_host_config_register_io_memory_noswap(PCIHostState *s); diff --git a/hw/sh_pci.c b/hw/sh_pci.c index 52dc02e1e..abe4c7568 100644 --- a/hw/sh_pci.c +++ b/hw/sh_pci.c @@ -24,6 +24,7 @@ #include "hw.h" #include "sh.h" #include "pci.h" +#include "pci_host.h" #include "sh_pci.h" #include "bswap.h" diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c index a0d7d07ad..153c6514f 100644 --- a/hw/versatile_pci.c +++ b/hw/versatile_pci.c @@ -9,6 +9,7 @@ #include "sysbus.h" #include "pci.h" +#include "pci_host.h" typedef struct { SysBusDevice busdev; -- cgit v1.2.3 From 4677d8ed9db8564fb0b02c1d012d4b25de633290 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 12 Nov 2009 14:58:31 +0900 Subject: pci: simplify (pci_/pcie_mmcfg_)data_read() Remove switch on length: we don't care about high bits for value, so just return all ones if no device. And add one assert(). Signed-off-by: Michael S. Tsirkin Acked-by: Isaku Yamahata --- hw/pci_host.c | 22 ++++++---------------- hw/pcie_host.c | 26 +++++--------------------- 2 files changed, 11 insertions(+), 37 deletions(-) diff --git a/hw/pci_host.c b/hw/pci_host.c index f4518dce7..4a29f4490 100644 --- a/hw/pci_host.c +++ b/hw/pci_host.c @@ -71,25 +71,15 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len) uint32_t config_addr = pci_addr_to_config(addr); uint32_t val; + assert(len == 1 || len == 2 || len == 4); if (!pci_dev) { - switch(len) { - case 1: - val = 0xff; - break; - case 2: - val = 0xffff; - break; - default: - case 4: - val = 0xffffffff; - break; - } - } else { - val = pci_dev->config_read(pci_dev, config_addr, len); - PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n", - __func__, pci_dev->name, config_addr, val, len); + return ~0x0; } + val = pci_dev->config_read(pci_dev, config_addr, len); + PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n", + __func__, pci_dev->name, config_addr, val, len); + return val; } diff --git a/hw/pcie_host.c b/hw/pcie_host.c index b52fec681..1dbc94ef6 100644 --- a/hw/pcie_host.c +++ b/hw/pcie_host.c @@ -65,31 +65,15 @@ static void pcie_mmcfg_data_write(PCIBus *s, PCIE_MMCFG_CONFOFFSET(mmcfg_addr), val, len); } -static uint32_t pcie_mmcfg_data_read(PCIBus *s, - uint32_t mmcfg_addr, int len) +static uint32_t pcie_mmcfg_data_read(PCIBus *s, uint32_t addr, int len) { - PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, mmcfg_addr); - uint32_t val; + PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, addr); + assert(len == 1 || len == 2 || len == 4); if (!pci_dev) { - switch(len) { - case 1: - val = 0xff; - break; - case 2: - val = 0xffff; - break; - default: - case 4: - val = 0xffffffff; - break; - } - } else { - val = pci_dev->config_read(pci_dev, - PCIE_MMCFG_CONFOFFSET(mmcfg_addr), len); + return ~0x0; } - - return val; + return pci_dev->config_read(pci_dev, PCIE_MMCFG_CONFOFFSET(addr), len); } static void pcie_mmcfg_data_writeb(void *opaque, -- cgit v1.2.3 From 7ac901cd18c382b9e7a07ac0b3a47f86d1ed4c1d Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:32 +0900 Subject: pci: remove pci_addr_to_config() by open code This patch removes pci_addr_to_config() and open code it as suggested by Michael S. Tsirkin . Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci_host.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/hw/pci_host.c b/hw/pci_host.c index 4a29f4490..ccefa34a4 100644 --- a/hw/pci_host.c +++ b/hw/pci_host.c @@ -47,15 +47,10 @@ static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr) return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn)); } -static inline uint32_t pci_addr_to_config(uint32_t addr) -{ - return addr & (PCI_CONFIG_SPACE_SIZE - 1); -} - void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len) { PCIDevice *pci_dev = pci_addr_to_dev(s, addr); - uint32_t config_addr = pci_addr_to_config(addr); + uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1); if (!pci_dev) return; @@ -68,7 +63,7 @@ void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len) uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len) { PCIDevice *pci_dev = pci_addr_to_dev(s, addr); - uint32_t config_addr = pci_addr_to_config(addr); + uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1); uint32_t val; assert(len == 1 || len == 2 || len == 4); -- cgit v1.2.3 From 8d6514f8dd2a8102ec3d577b13cb565fb9cfe73c Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 13:17:23 +0200 Subject: pci: rename (pci_/pcie_mmcfg_)addr_to_dev This patch renames pci_addr_to_dev(), pcie_mmcfg_addr_to_dev() to pci_dev_find_by_addr(), pcie_dev_find_by_mmcfg_addr() as "Michael S. Tsirkin" suggested. Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci_host.c | 6 +++--- hw/pcie_host.c | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/pci_host.c b/hw/pci_host.c index ccefa34a4..403d0408c 100644 --- a/hw/pci_host.c +++ b/hw/pci_host.c @@ -40,7 +40,7 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0) */ /* the helper functio to get a PCIDeice* for a given pci address */ -static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr) +static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr) { uint8_t bus_num = (addr >> 16) & 0xff; uint8_t devfn = (addr >> 8) & 0xff; @@ -49,7 +49,7 @@ static inline PCIDevice *pci_addr_to_dev(PCIBus *bus, uint32_t addr) void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len) { - PCIDevice *pci_dev = pci_addr_to_dev(s, addr); + PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr); uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1); if (!pci_dev) @@ -62,7 +62,7 @@ void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len) uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len) { - PCIDevice *pci_dev = pci_addr_to_dev(s, addr); + PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr); uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1); uint32_t val; diff --git a/hw/pcie_host.c b/hw/pcie_host.c index 1dbc94ef6..fbd6c3759 100644 --- a/hw/pcie_host.c +++ b/hw/pcie_host.c @@ -46,7 +46,8 @@ /* a helper function to get a PCIDevice for a given mmconfig address */ -static inline PCIDevice *pcie_mmcfg_addr_to_dev(PCIBus *s, uint32_t mmcfg_addr) +static inline PCIDevice *pcie_dev_find_by_mmcfg_addr(PCIBus *s, + uint32_t mmcfg_addr) { return pci_find_device(s, PCIE_MMCFG_BUS(mmcfg_addr), PCI_SLOT(PCIE_MMCFG_DEVFN(mmcfg_addr)), @@ -56,7 +57,7 @@ static inline PCIDevice *pcie_mmcfg_addr_to_dev(PCIBus *s, uint32_t mmcfg_addr) static void pcie_mmcfg_data_write(PCIBus *s, uint32_t mmcfg_addr, uint32_t val, int len) { - PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, mmcfg_addr); + PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr); if (!pci_dev) return; @@ -67,7 +68,7 @@ static void pcie_mmcfg_data_write(PCIBus *s, static uint32_t pcie_mmcfg_data_read(PCIBus *s, uint32_t addr, int len) { - PCIDevice *pci_dev = pcie_mmcfg_addr_to_dev(s, addr); + PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, addr); assert(len == 1 || len == 2 || len == 4); if (!pci_dev) { -- cgit v1.2.3 From f08b32fe959c157d3c3acdad9c7bfe56b5597af1 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:34 +0900 Subject: pci: shorten pci_host_{conf, data}_register_xxx function a bit. pci_host_data_register_io_memory and its variants are too long a bit. So shorten them. Now they are pci_host_{conf, data}_register_{mmio, mmio_noswap, ioport}() Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/apb_pci.c | 4 ++-- hw/grackle_pci.c | 8 ++++---- hw/pci_host.c | 8 ++++---- hw/pci_host.h | 8 ++++---- hw/piix_pci.c | 2 +- hw/ppc4xx_pci.c | 2 +- hw/ppce500_pci.c | 4 ++-- hw/prep_pci.c | 2 +- hw/unin_pci.c | 16 ++++++++-------- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/hw/apb_pci.c b/hw/apb_pci.c index 1748d8dc7..f2ed136fd 100644 --- a/hw/apb_pci.c +++ b/hw/apb_pci.c @@ -236,10 +236,10 @@ static int pci_pbm_init_device(SysBusDevice *dev) pci_apb_iowrite, s); sysbus_init_mmio(dev, 0x10000ULL, pci_ioport); /* mem_config */ - pci_mem_config = pci_host_config_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x10ULL, pci_mem_config); /* mem_data */ - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data); return 0; } diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c index f3a8a7da1..089d1fba0 100644 --- a/hw/grackle_pci.c +++ b/hw/grackle_pci.c @@ -108,8 +108,8 @@ static int pci_grackle_init_device(SysBusDevice *dev) s = FROM_SYSBUS(GrackleState, dev); - pci_mem_config = pci_host_config_register_io_memory(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); @@ -126,8 +126,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev) s = FROM_SYSBUS(GrackleState, dev); - pci_mem_config = pci_host_config_register_io_memory(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; diff --git a/hw/pci_host.c b/hw/pci_host.c index 403d0408c..45ddcd1e8 100644 --- a/hw/pci_host.c +++ b/hw/pci_host.c @@ -116,7 +116,7 @@ static CPUReadMemoryFunc * const pci_host_config_read[] = { &pci_host_config_readl, }; -int pci_host_config_register_io_memory(PCIHostState *s) +int pci_host_conf_register_mmio(PCIHostState *s) { return cpu_register_io_memory(pci_host_config_read, pci_host_config_write, s); @@ -156,7 +156,7 @@ static CPUReadMemoryFunc * const pci_host_config_read_noswap[] = { &pci_host_config_readl_noswap, }; -int pci_host_config_register_io_memory_noswap(PCIHostState *s) +int pci_host_conf_register_mmio_noswap(PCIHostState *s) { return cpu_register_io_memory(pci_host_config_read_noswap, pci_host_config_write_noswap, s); @@ -180,7 +180,7 @@ static uint32_t pci_host_config_readl_ioport(void *opaque, uint32_t addr) return val; } -void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s) +void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s) { register_ioport_write(ioport, 4, 4, pci_host_config_writel_ioport, s); register_ioport_read(ioport, 4, 4, pci_host_config_readl_ioport, s); @@ -203,7 +203,7 @@ static CPUReadMemoryFunc * const pci_host_data_read_mmio[] = { pci_host_data_readl_mmio, }; -int pci_host_data_register_io_memory(PCIHostState *s) +int pci_host_data_register_mmio(PCIHostState *s) { return cpu_register_io_memory(pci_host_data_read_mmio, pci_host_data_write_mmio, diff --git a/hw/pci_host.h b/hw/pci_host.h index 7cfa69356..cf3a3393d 100644 --- a/hw/pci_host.h +++ b/hw/pci_host.h @@ -40,12 +40,12 @@ void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len); uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len); /* for mmio */ -int pci_host_config_register_io_memory(PCIHostState *s); -int pci_host_config_register_io_memory_noswap(PCIHostState *s); -int pci_host_data_register_io_memory(PCIHostState *s); +int pci_host_conf_register_mmio(PCIHostState *s); +int pci_host_conf_register_mmio_noswap(PCIHostState *s); +int pci_host_data_register_mmio(PCIHostState *s); /* for ioio */ -void pci_host_config_register_ioport(pio_addr_t ioport, PCIHostState *s); +void pci_host_conf_register_ioport(pio_addr_t ioport, PCIHostState *s); void pci_host_data_register_ioport(pio_addr_t ioport, PCIHostState *s); #endif /* PCI_HOST_H */ diff --git a/hw/piix_pci.c b/hw/piix_pci.c index 5fb7d7be9..a44f941dc 100644 --- a/hw/piix_pci.c +++ b/hw/piix_pci.c @@ -180,7 +180,7 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev) { I440FXState *s = FROM_SYSBUS(I440FXState, dev); - pci_host_config_register_ioport(0xcf8, s); + pci_host_conf_register_ioport(0xcf8, s); pci_host_data_register_ioport(0xcfc, s); return 0; diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c index 3aa7489e2..2d00b6122 100644 --- a/hw/ppc4xx_pci.c +++ b/hw/ppc4xx_pci.c @@ -378,7 +378,7 @@ PCIBus *ppc4xx_pci_init(CPUState *env, qemu_irq pci_irqs[4], cpu_register_physical_memory(config_space + PCIC0_CFGADDR, 4, index); /* CFGDATA */ - index = pci_host_data_register_io_memory(&controller->pci_state); + index = pci_host_data_register_mmio(&controller->pci_state); if (index < 0) goto free; cpu_register_physical_memory(config_space + PCIC0_CFGDATA, 4, index); diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c index 223de3ae3..a72fb86d2 100644 --- a/hw/ppce500_pci.c +++ b/hw/ppce500_pci.c @@ -293,13 +293,13 @@ PCIBus *ppce500_pci_init(qemu_irq pci_irqs[4], target_phys_addr_t registers) controller->pci_dev = d; /* CFGADDR */ - index = pci_host_config_register_io_memory_noswap(&controller->pci_state); + index = pci_host_conf_register_mmio_noswap(&controller->pci_state); if (index < 0) goto free; cpu_register_physical_memory(registers + PCIE500_CFGADDR, 4, index); /* CFGDATA */ - index = pci_host_data_register_io_memory(&controller->pci_state); + index = pci_host_data_register_mmio(&controller->pci_state); if (index < 0) goto free; cpu_register_physical_memory(registers + PCIE500_CFGDATA, 4, index); diff --git a/hw/prep_pci.c b/hw/prep_pci.c index 80e20ac1a..19f028c7b 100644 --- a/hw/prep_pci.c +++ b/hw/prep_pci.c @@ -128,7 +128,7 @@ PCIBus *pci_prep_init(qemu_irq *pic) s->bus = pci_register_bus(NULL, "pci", prep_set_irq, prep_map_irq, pic, 0, 4); - pci_host_config_register_ioport(0xcf8, s); + pci_host_conf_register_ioport(0xcf8, s); pci_host_data_register_ioport(0xcfc, s); diff --git a/hw/unin_pci.c b/hw/unin_pci.c index fe13e7b3e..5b3f118fc 100644 --- a/hw/unin_pci.c +++ b/hw/unin_pci.c @@ -84,8 +84,8 @@ static int pci_unin_main_init_device(SysBusDevice *dev) /* Uninorth main bus */ s = FROM_SYSBUS(UNINState, dev); - pci_mem_config = pci_host_config_register_io_memory(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); @@ -103,8 +103,8 @@ static int pci_dec_21154_init_device(SysBusDevice *dev) s = FROM_SYSBUS(UNINState, dev); // XXX: s = &pci_bridge[2]; - pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio_noswap(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; @@ -118,8 +118,8 @@ static int pci_unin_agp_init_device(SysBusDevice *dev) /* Uninorth AGP bus */ s = FROM_SYSBUS(UNINState, dev); - pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio_noswap(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; @@ -133,8 +133,8 @@ static int pci_unin_internal_init_device(SysBusDevice *dev) /* Uninorth internal bus */ s = FROM_SYSBUS(UNINState, dev); - pci_mem_config = pci_host_config_register_io_memory_noswap(&s->host_state); - pci_mem_data = pci_host_data_register_io_memory(&s->host_state); + pci_mem_config = pci_host_conf_register_mmio_noswap(&s->host_state); + pci_mem_data = pci_host_data_register_mmio(&s->host_state); sysbus_init_mmio(dev, 0x1000, pci_mem_config); sysbus_init_mmio(dev, 0x1000, pci_mem_data); return 0; -- cgit v1.2.3 From 070297d2609fea4fd7afec05eb9a43688b91fb79 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:35 +0900 Subject: pci: remove pci_sub_bus() by open coding. Because pci_sub_bus() is used only once so eliminate it by open coding as suggested by "Michael S. Tsirkin" . Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 040fa767f..aa677b2db 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -239,13 +239,6 @@ int pci_bus_num(PCIBus *s) return s->parent_dev->config[PCI_SECONDARY_BUS]; } -static uint8_t pci_sub_bus(PCIBus *s) -{ - if (!s->parent_dev) - return 255; /* pci host bridge */ - return s->parent_dev->config[PCI_SUBORDINATE_BUS]; -} - static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) { PCIDevice *s = container_of(pv, PCIDevice, config); @@ -1180,7 +1173,10 @@ PCIBus *pci_find_bus(PCIBus *bus, int bus_num) /* try child bus */ QLIST_FOREACH(sec, &bus->child, sibling) { - if (pci_bus_num(sec) <= bus_num && bus_num <= pci_sub_bus(sec)) { + + if (!bus->parent_dev /* pci host bridge */ + || (pci_bus_num(sec) <= bus_num && + bus->parent_dev->config[PCI_SUBORDINATE_BUS])) { return pci_find_bus(sec, bus_num); } } -- cgit v1.2.3 From c469e1dd6375c50bc61d995dde4714fc19f411ed Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:36 +0900 Subject: pci: s/pci_find_host_bus/pci_find_root_bus/g This patch renames pci_find_host_bus() to pci_find_root_bus() as suggested by "Michael S. Tsirkin" . Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci-hotplug.c | 4 ++-- hw/pci.c | 8 ++++---- hw/pci.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c index a25449814..081d6d1ac 100644 --- a/hw/pci-hotplug.c +++ b/hw/pci-hotplug.c @@ -113,7 +113,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict) if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) { goto err; } - dev = pci_find_device(pci_find_host_bus(0), pci_bus, slot, 0); + dev = pci_find_device(pci_find_root_bus(0), pci_bus, slot, 0); if (!dev) { monitor_printf(mon, "no pci device with address %s\n", pci_addr); goto err; @@ -257,7 +257,7 @@ void pci_device_hot_remove(Monitor *mon, const char *pci_addr) return; } - d = pci_find_device(pci_find_host_bus(0), bus, slot, 0); + d = pci_find_device(pci_find_root_bus(0), bus, slot, 0); if (!d) { monitor_printf(mon, "slot %d empty\n", slot); return; diff --git a/hw/pci.c b/hw/pci.c index aa677b2db..d8f5fa0ed 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -146,7 +146,7 @@ static void pci_host_bus_register(int domain, PCIBus *bus) QLIST_INSERT_HEAD(&host_buses, host, next); } -PCIBus *pci_find_host_bus(int domain) +PCIBus *pci_find_root_bus(int domain) { struct PCIHostBus *host; @@ -372,7 +372,7 @@ static int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned *s return -1; /* Note: QEMU doesn't implement domains other than 0 */ - if (!pci_find_bus(pci_find_host_bus(dom), bus)) + if (!pci_find_bus(pci_find_root_bus(dom), bus)) return -1; *domp = dom; @@ -402,7 +402,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr) if (!devaddr) { *devfnp = -1; - return pci_find_bus(pci_find_host_bus(0), 0); + return pci_find_bus(pci_find_root_bus(0), 0); } if (pci_parse_devaddr(devaddr, &dom, &bus, &slot) < 0) { @@ -410,7 +410,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr) } *devfnp = slot << 3; - return pci_find_bus(pci_find_host_bus(0), bus); + return pci_find_bus(pci_find_root_bus(0), bus); } static void pci_init_cmask(PCIDevice *dev) diff --git a/hw/pci.h b/hw/pci.h index 2f213524c..ff5f36cee 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -295,7 +295,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, const char *default_devaddr); int pci_bus_num(PCIBus *s); void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d)); -PCIBus *pci_find_host_bus(int domain); +PCIBus *pci_find_root_bus(int domain); PCIBus *pci_find_bus(PCIBus *bus, int bus_num); PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function); PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr); -- cgit v1.2.3 From 42331e9f2fa2d98acc8faf31c4b04de8ea2d7129 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:37 +0900 Subject: pci_host: remove unnecessary & 0xff. This patch removes unnecessary & 0xff in pci_dev_find_by_addr(). Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci_host.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/pci_host.c b/hw/pci_host.c index 45ddcd1e8..eeb8deeaf 100644 --- a/hw/pci_host.c +++ b/hw/pci_host.c @@ -42,8 +42,9 @@ do { printf("pci_host_data: " fmt , ## __VA_ARGS__); } while (0) /* the helper functio to get a PCIDeice* for a given pci address */ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr) { - uint8_t bus_num = (addr >> 16) & 0xff; - uint8_t devfn = (addr >> 8) & 0xff; + uint8_t bus_num = addr >> 16; + uint8_t devfn = addr >> 8; + return pci_find_device(bus, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn)); } -- cgit v1.2.3 From c34369d48c9b94f5a71f65cc97caaa5a75ffad5c Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:38 +0900 Subject: pci: kill unnecessary included in pci.c including pci_host.h isn't needed by pci.c. This patch kills it. Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/pci.c b/hw/pci.c index d8f5fa0ed..c3ad1bbb8 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -23,7 +23,6 @@ */ #include "hw.h" #include "pci.h" -#include "pci_host.h" #include "monitor.h" #include "net.h" #include "sysemu.h" -- cgit v1.2.3 From 3e21ffc954c09e90b25a446813ff1c0b26817aef Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:39 +0900 Subject: pci: clean up of pci_init_wmask(). This patch replaces for loop by memset in pci_init_wmask(). Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index c3ad1bbb8..64cf0a8a5 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -426,15 +426,15 @@ static void pci_init_cmask(PCIDevice *dev) static void pci_init_wmask(PCIDevice *dev) { - int i; int config_size = pci_config_size(dev); dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff; dev->wmask[PCI_INTERRUPT_LINE] = 0xff; pci_set_word(dev->wmask + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i) - dev->wmask[i] = 0xff; + + memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff, + config_size - PCI_CONFIG_HEADER_SIZE); } static void pci_init_wmask_bridge(PCIDevice *d) -- cgit v1.2.3 From 3c217c14f58c0146a0dbca01716cd850a63a0e81 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:40 +0900 Subject: pci: remove some unnecessary comment in pci.h This patch removes some comment which should go into commit log in pci.h. Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.h | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/hw/pci.h b/hw/pci.h index ff5f36cee..b2c2c92f2 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -382,17 +382,10 @@ typedef struct { PCIConfigWriteFunc *config_write; /* pci config header type */ - uint8_t header_type; /* this is necessary for initialization - * code to know its header type before - * device specific code can initialize - * configuration space. - */ + uint8_t header_type; /* pcie stuff */ - int is_express; /* is this device pci express? - * initialization code needs to know this before - * each specific device initialization. - */ + int is_express; /* is this device pci express? */ } PCIDeviceInfo; void pci_qdev_register(PCIDeviceInfo *info); -- cgit v1.2.3 From fb47a2e983f3e0b4c9d36fe0d31ed8a1224e767b Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:41 +0900 Subject: pci: move typedef, PCIHostState, PCIExpressHost to qemu-common.h. This patch moves two typedefs, PCIHostState and PCIExpressHost to qemu-common.h for consistency as PCIBus and PCIDevice are typedefed in qemu-common.h. Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci_host.h | 4 ++-- hw/pcie_host.h | 4 ++-- qemu-common.h | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/pci_host.h b/hw/pci_host.h index cf3a3393d..a006687f8 100644 --- a/hw/pci_host.h +++ b/hw/pci_host.h @@ -30,11 +30,11 @@ #include "sysbus.h" -typedef struct { +struct PCIHostState { SysBusDevice busdev; uint32_t config_reg; PCIBus *bus; -} PCIHostState; +}; void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len); uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len); diff --git a/hw/pcie_host.h b/hw/pcie_host.h index a7771c912..7754ac94e 100644 --- a/hw/pcie_host.h +++ b/hw/pcie_host.h @@ -24,7 +24,7 @@ #include "pci_host.h" -typedef struct { +struct PCIExpressHost { PCIHostState pci; /* express part */ @@ -37,7 +37,7 @@ typedef struct { /* result of cpu_register_io_memory() to map MMCONFIG area */ int mmio_index; -} PCIExpressHost; +}; int pcie_host_init(PCIExpressHost *e); void pcie_host_mmcfg_unmap(PCIExpressHost *e); diff --git a/qemu-common.h b/qemu-common.h index b1e038bd0..57af677f0 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -198,6 +198,8 @@ typedef struct i2c_bus i2c_bus; typedef struct i2c_slave i2c_slave; typedef struct SMBusDevice SMBusDevice; typedef struct QEMUTimer QEMUTimer; +typedef struct PCIHostState PCIHostState; +typedef struct PCIExpressHost PCIExpressHost; typedef struct PCIBus PCIBus; typedef struct PCIDevice PCIDevice; typedef struct SerialState SerialState; -- cgit v1.2.3 From 2c56b44b88d913c4f7acb444071052b55b37da34 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:42 +0900 Subject: pci: remove unused constants This patch removes unused constants committed by fb23162885f7fd8cf7334bed22c25ac32c7d8b9d. Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/hw/pci.h b/hw/pci.h index b2c2c92f2..6a868f95d 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -101,14 +101,6 @@ typedef struct PCIIORegion { #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ #define PCI_COMMAND_MASTER 0x4 /* Enable bus master */ -#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ -#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ -#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ -#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ -#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ -#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ -#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ -#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */ #define PCI_STATUS 0x06 /* 16 bits */ #define PCI_REVISION_ID 0x08 /* 8 bits */ #define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ @@ -128,7 +120,6 @@ typedef struct PCIIORegion { #define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ #define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */ #define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */ -#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */ #define PCI_IO_BASE 0x1c /* I/O range behind the bridge */ #define PCI_IO_LIMIT 0x1d #define PCI_IO_RANGE_TYPE_32 0x01 -- cgit v1.2.3 From ec50344230aad67a867ac59e4a0cd7233149484c Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:43 +0900 Subject: pci: clean up of pci_update_mappings() This patch converts r->size == 0 to !r_size. Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci.c b/hw/pci.c index 64cf0a8a5..d6f647cc2 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -733,7 +733,7 @@ static void pci_update_mappings(PCIDevice *d) r = &d->io_regions[i]; /* this region isn't registered */ - if (r->size == 0) + if (!r->size) continue; if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { -- cgit v1.2.3 From 876a350d3daed88c5677397c287c6210cf163f6c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 12 Nov 2009 13:47:17 +0200 Subject: pci: split up up pci_update mappings Split bar address math into a separate function. In particular, this gets rid of an ugly forward goto into scope that we have there. Signed-off-by: Michael S. Tsirkin Acked-by: Isaku Yamahata --- hw/pci.c | 125 ++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 68 insertions(+), 57 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index d6f647cc2..49d06489e 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -721,14 +721,77 @@ static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size, } } +static pcibus_t pci_bar_address(PCIDevice *d, + int reg, uint8_t type, pcibus_t size) +{ + pcibus_t new_addr, last_addr; + int bar = pci_bar(d, reg); + uint16_t cmd = pci_get_word(d->config + PCI_COMMAND); + + if (type & PCI_BASE_ADDRESS_SPACE_IO) { + if (!(cmd & PCI_COMMAND_IO)) { + return PCI_BAR_UNMAPPED; + } + new_addr = pci_get_long(d->config + bar) & ~(size - 1); + last_addr = new_addr + size - 1; + /* NOTE: we have only 64K ioports on PC */ + if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) { + return PCI_BAR_UNMAPPED; + } + return new_addr; + } + + if (!(cmd & PCI_COMMAND_MEMORY)) { + return PCI_BAR_UNMAPPED; + } + if (type & PCI_BASE_ADDRESS_MEM_TYPE_64) { + new_addr = pci_get_quad(d->config + bar); + } else { + new_addr = pci_get_long(d->config + bar); + } + /* the ROM slot has a specific enable bit */ + if (reg == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) { + return PCI_BAR_UNMAPPED; + } + new_addr &= ~(size - 1); + last_addr = new_addr + size - 1; + /* NOTE: we do not support wrapping */ + /* XXX: as we cannot support really dynamic + mappings, we handle specific values as invalid + mappings. */ + if (last_addr <= new_addr || new_addr == 0 || + last_addr == PCI_BAR_UNMAPPED) { + return PCI_BAR_UNMAPPED; + } + + /* Now pcibus_t is 64bit. + * Check if 32 bit BAR wraps around explicitly. + * Without this, PC ide doesn't work well. + * TODO: remove this work around. + */ + if (!(type & PCI_BASE_ADDRESS_MEM_TYPE_64) && last_addr >= UINT32_MAX) { + return PCI_BAR_UNMAPPED; + } + + /* + * OS is allowed to set BAR beyond its addressable + * bits. For example, 32 bit OS can set 64bit bar + * to >4G. Check it. TODO: we might need to support + * it in the future for e.g. PAE. + */ + if (last_addr >= TARGET_PHYS_ADDR_MAX) { + return PCI_BAR_UNMAPPED; + } + + return new_addr; +} + static void pci_update_mappings(PCIDevice *d) { PCIIORegion *r; - int cmd, i; - pcibus_t last_addr, new_addr; - pcibus_t filtered_size; + int i; + pcibus_t new_addr, filtered_size; - cmd = pci_get_word(d->config + PCI_COMMAND); for(i = 0; i < PCI_NUM_REGIONS; i++) { r = &d->io_regions[i]; @@ -736,59 +799,7 @@ static void pci_update_mappings(PCIDevice *d) if (!r->size) continue; - if (r->type & PCI_BASE_ADDRESS_SPACE_IO) { - if (cmd & PCI_COMMAND_IO) { - new_addr = pci_get_long(d->config + pci_bar(d, i)); - new_addr = new_addr & ~(r->size - 1); - last_addr = new_addr + r->size - 1; - /* NOTE: we have only 64K ioports on PC */ - if (last_addr <= new_addr || new_addr == 0 || - last_addr >= 0x10000) { - new_addr = PCI_BAR_UNMAPPED; - } - } else { - new_addr = PCI_BAR_UNMAPPED; - } - } else { - if (cmd & PCI_COMMAND_MEMORY) { - if (r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { - new_addr = pci_get_quad(d->config + pci_bar(d, i)); - } else { - new_addr = pci_get_long(d->config + pci_bar(d, i)); - } - /* the ROM slot has a specific enable bit */ - if (i == PCI_ROM_SLOT && !(new_addr & PCI_ROM_ADDRESS_ENABLE)) - goto no_mem_map; - new_addr = new_addr & ~(r->size - 1); - last_addr = new_addr + r->size - 1; - /* NOTE: we do not support wrapping */ - /* XXX: as we cannot support really dynamic - mappings, we handle specific values as invalid - mappings. */ - if (last_addr <= new_addr || new_addr == 0 || - last_addr == PCI_BAR_UNMAPPED || - - /* Now pcibus_t is 64bit. - * Check if 32 bit BAR wrap around explicitly. - * Without this, PC ide doesn't work well. - * TODO: remove this work around. - */ - (!(r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) && - last_addr >= UINT32_MAX) || - - /* - * OS is allowed to set BAR beyond its addressable - * bits. For example, 32 bit OS can set 64bit bar - * to >4G. Check it. - */ - last_addr >= TARGET_PHYS_ADDR_MAX) { - new_addr = PCI_BAR_UNMAPPED; - } - } else { - no_mem_map: - new_addr = PCI_BAR_UNMAPPED; - } - } + new_addr = pci_bar_address(d, i, r->type, r->size); /* bridge filtering */ filtered_size = r->size; -- cgit v1.2.3 From b47b0706f15f9427ffc48b0db61f1b6e52b98b2a Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:45 +0900 Subject: pci: remove magic number, 256 in pci.c This patch replaces magic number, 256, with ARRAY_SIZE(). Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index 49d06489e..6d94286a4 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -487,7 +487,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, uint8_t header_type) { if (devfn < 0) { - for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { + for(devfn = bus->devfn_min ; devfn < ARRAY_SIZE(bus->devices); + devfn += 8) { if (!bus->devices[devfn]) goto found; } @@ -1035,7 +1036,7 @@ static void pci_for_each_device_under_bus(PCIBus *bus, PCIDevice *d; int devfn; - for(devfn = 0; devfn < 256; devfn++) { + for(devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) { d = bus->devices[devfn]; if (d) fn(bus, d); -- cgit v1.2.3 From 10c9c329da60fe64ad24dba6f81044559ff15f9b Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:46 +0900 Subject: pci: fix pci_config_get_io_base(). fix typo in pci_config_get_io_base(). Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/pci.c b/hw/pci.c index 6d94286a4..bc566e594 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -630,7 +630,7 @@ static uint32_t pci_config_get_io_base(PCIDevice *d, val = ((uint32_t)d->config[base] & PCI_IO_RANGE_MASK) << 8; if (d->config[base] & PCI_IO_RANGE_TYPE_32) { - val |= (uint32_t)pci_get_word(d->config + PCI_IO_BASE_UPPER16) << 16; + val |= (uint32_t)pci_get_word(d->config + base_upper16) << 16; } return val; } -- cgit v1.2.3 From d46636b88339ecc2cb8d10113f45ada164817773 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Thu, 12 Nov 2009 14:58:47 +0900 Subject: pci: pci bridge related clean up. - fix bridge prefetchable memory accesser to check 64bit or not. - use pcibus_t consistently instead mixing pcibus_t and uint64_t. Signed-off-by: Isaku Yamahata Signed-off-by: Michael S. Tsirkin --- hw/pci.c | 18 +++++++++++------- hw/pci.h | 1 + 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index bc566e594..e26b3d034 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -635,19 +635,23 @@ static uint32_t pci_config_get_io_base(PCIDevice *d, return val; } -static uint64_t pci_config_get_memory_base(PCIDevice *d, uint32_t base) +static pcibus_t pci_config_get_memory_base(PCIDevice *d, uint32_t base) { - return ((uint64_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK) + return ((pcibus_t)pci_get_word(d->config + base) & PCI_MEMORY_RANGE_MASK) << 16; } -static uint64_t pci_config_get_pref_base(PCIDevice *d, +static pcibus_t pci_config_get_pref_base(PCIDevice *d, uint32_t base, uint32_t upper) { - uint64_t val; - val = ((uint64_t)pci_get_word(d->config + base) & - PCI_PREF_RANGE_MASK) << 16; - val |= (uint64_t)pci_get_long(d->config + upper) << 32; + pcibus_t tmp; + pcibus_t val; + + tmp = (pcibus_t)pci_get_word(d->config + base); + val = (tmp & PCI_PREF_RANGE_MASK) << 16; + if (tmp & PCI_PREF_RANGE_TYPE_64) { + val |= (pcibus_t)pci_get_long(d->config + upper) << 32; + } return val; } diff --git a/hw/pci.h b/hw/pci.h index 6a868f95d..0baf69bd5 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -131,6 +131,7 @@ typedef struct PCIIORegion { #define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */ #define PCI_PREF_MEMORY_LIMIT 0x26 #define PCI_PREF_RANGE_MASK (~0x0fUL) +#define PCI_PREF_RANGE_TYPE_64 0x01 #define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */ #define PCI_PREF_LIMIT_UPPER32 0x2c #define PCI_SUBSYSTEM_VENDOR_ID 0x2c /* 16 bits */ -- cgit v1.2.3 From 88a9556430df57cbe7666e4e4cf78c3bd3bc8220 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 12 Nov 2009 13:54:31 +0200 Subject: pci: convert goto into scope in bridge_filter goto into scope is evil. rearrange pci_bridge_filter so that we always go to end of function on error. Signed-off-by: Michael S. Tsirkin Acked-by: Isaku Yamahata --- hw/pci.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index e26b3d034..8cf008d31 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -717,13 +717,14 @@ static void pci_bridge_filter(PCIDevice *d, pcibus_t *addr, pcibus_t *size, } if (base > limit) { - no_map: - *addr = PCI_BAR_UNMAPPED; - *size = 0; - } else { - *addr = base; - *size = limit - base + 1; + goto no_map; } + *addr = base; + *size = limit - base + 1; + return; +no_map: + *addr = PCI_BAR_UNMAPPED; + *size = 0; } static pcibus_t pci_bar_address(PCIDevice *d, -- cgit v1.2.3 From b5f28bcaeec3ca54755f24ae665c4028fc598d77 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 24 Nov 2009 16:44:15 +0200 Subject: msix: add helper to unuse all msix entries will be used by virtio on soft reset Signed-off-by: Michael S. Tsirkin --- hw/msix.c | 7 +++++++ hw/msix.h | 1 + 2 files changed, 8 insertions(+) diff --git a/hw/msix.c b/hw/msix.c index 548ffd5c8..d49944111 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -378,3 +378,10 @@ void msix_vector_unuse(PCIDevice *dev, unsigned vector) if (vector < dev->msix_entries_nr && dev->msix_entry_used[vector]) --dev->msix_entry_used[vector]; } + +void msix_unuse_all_vectors(PCIDevice *dev) +{ + if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) + return; + msix_free_irq_entries(dev); +} diff --git a/hw/msix.h b/hw/msix.h index 39fa568f9..a9f7993c3 100644 --- a/hw/msix.h +++ b/hw/msix.h @@ -25,6 +25,7 @@ uint32_t msix_bar_size(PCIDevice *dev); int msix_vector_use(PCIDevice *dev, unsigned vector); void msix_vector_unuse(PCIDevice *dev, unsigned vector); +void msix_unuse_all_vectors(PCIDevice *dev); void msix_notify(PCIDevice *dev, unsigned vector); -- cgit v1.2.3 From 1b8e9b274287ea7e2256244e62ed285b7d83e0ad Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 24 Nov 2009 16:45:35 +0200 Subject: virtio: do not reset msix state on soft reset msix state is managed by OS, not the driver, so it's wrong to touch it on io from driver. Mark all vectors unused instead. Signed-off-by: Michael S. Tsirkin --- hw/virtio-pci.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index aebcf9d0d..d222ce03f 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -185,8 +185,10 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case VIRTIO_PCI_QUEUE_PFN: pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT; - if (pa == 0) - virtio_pci_reset(&proxy->pci_dev.qdev); + if (pa == 0) { + virtio_reset(proxy->vdev); + msix_unuse_all_vectors(&proxy->pci_dev); + } else virtio_queue_set_addr(vdev, vdev->queue_sel, pa); break; @@ -199,8 +201,10 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val) break; case VIRTIO_PCI_STATUS: vdev->status = val & 0xFF; - if (vdev->status == 0) - virtio_pci_reset(&proxy->pci_dev.qdev); + if (vdev->status == 0) { + virtio_reset(proxy->vdev); + msix_unuse_all_vectors(&proxy->pci_dev); + } break; case VIRTIO_MSI_CONFIG_VECTOR: msix_vector_unuse(&proxy->pci_dev, vdev->config_vector); -- cgit v1.2.3 From ae1be0bbc127a9a6289873efdb7cb22c57d81a9d Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 25 Nov 2009 11:41:48 +0200 Subject: msix: fix mask bit state after reset PCI spec states that mask bit must be 1 after reset. Make it so. Signed-off-by: Michael S. Tsirkin --- hw/msix.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hw/msix.c b/hw/msix.c index d49944111..45f83dd71 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -217,6 +217,15 @@ void msix_mmio_map(PCIDevice *d, int region_num, d->msix_mmio_index); } +static void msix_mask_all(struct PCIDevice *dev, unsigned nentries) +{ + int vector; + for (vector = 0; vector < nentries; ++vector) { + unsigned offset = vector * MSIX_ENTRY_SIZE + MSIX_VECTOR_CTRL; + dev->msix_table_page[offset] |= MSIX_VECTOR_MASK; + } +} + /* Initialize the MSI-X structures. Note: if MSI-X is supported, BAR size is * modified, it should be retrieved with msix_bar_size. */ int msix_init(struct PCIDevice *dev, unsigned short nentries, @@ -234,6 +243,7 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries, sizeof *dev->msix_entry_used); dev->msix_table_page = qemu_mallocz(MSIX_PAGE_SIZE); + msix_mask_all(dev, nentries); dev->msix_mmio_index = cpu_register_io_memory(msix_mmio_read, msix_mmio_write, dev); @@ -353,6 +363,7 @@ void msix_reset(PCIDevice *dev) msix_free_irq_entries(dev); dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &= MSIX_ENABLE_MASK; memset(dev->msix_table_page, 0, MSIX_PAGE_SIZE); + msix_mask_all(dev, dev->msix_entries_nr); } /* PCI spec suggests that devices make it possible for software to configure -- cgit v1.2.3 From 1f944c661a821774e7b8cfbf5560a238795f2a60 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 25 Nov 2009 12:00:10 +0200 Subject: msix: fix reset value for enable bit On reset, we currently clear all bits in msix control register *except* enable bit. This is wrong: the spec says we should clear writeable bits: function mask and enable bit. Correct this. Signed-off-by: Michael S. Tsirkin --- hw/msix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/msix.c b/hw/msix.c index 45f83dd71..785e097d8 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -361,7 +361,8 @@ void msix_reset(PCIDevice *dev) if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) return; msix_free_irq_entries(dev); - dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &= MSIX_ENABLE_MASK; + dev->config[dev->msix_cap + MSIX_ENABLE_OFFSET] &= + ~dev->wmask[dev->msix_cap + MSIX_ENABLE_OFFSET]; memset(dev->msix_table_page, 0, MSIX_PAGE_SIZE); msix_mask_all(dev, dev->msix_entries_nr); } -- cgit v1.2.3 From 98304c846d8866dae6322ef400ce6595b23cfc41 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 25 Nov 2009 12:24:14 +0200 Subject: msix: clear pending bit of an unused vector PCI spec states: if a masked vector has its Pending bit set, and the associated underlying interrupt events are somehow satisfied (usually by software though the exact manner is function-specific), the function must clear the Pending bit, to avoid sending a spurious interrupt message later when software unmasks the vector. In our case this happens if vector becomes unused. Clear pending bit in this case. Signed-off-by: Michael S. Tsirkin --- hw/msix.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/hw/msix.c b/hw/msix.c index 785e097d8..4bc614723 100644 --- a/hw/msix.c +++ b/hw/msix.c @@ -105,14 +105,6 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries, return 0; } -static void msix_free_irq_entries(PCIDevice *dev) -{ - int vector; - - for (vector = 0; vector < dev->msix_entries_nr; ++vector) - dev->msix_entry_used[vector] = 0; -} - /* Handle MSI-X capability config write. */ void msix_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len) @@ -271,6 +263,16 @@ err_index: return ret; } +static void msix_free_irq_entries(PCIDevice *dev) +{ + int vector; + + for (vector = 0; vector < dev->msix_entries_nr; ++vector) { + dev->msix_entry_used[vector] = 0; + msix_clr_pending(dev, vector); + } +} + /* Clean up resources for the device. */ int msix_uninit(PCIDevice *dev) { @@ -387,8 +389,13 @@ int msix_vector_use(PCIDevice *dev, unsigned vector) /* Mark vector as unused. */ void msix_vector_unuse(PCIDevice *dev, unsigned vector) { - if (vector < dev->msix_entries_nr && dev->msix_entry_used[vector]) - --dev->msix_entry_used[vector]; + if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector]) { + return; + } + if (--dev->msix_entry_used[vector]) { + return; + } + msix_clr_pending(dev, vector); } void msix_unuse_all_vectors(PCIDevice *dev) -- cgit v1.2.3