aboutsummaryrefslogtreecommitdiff
path: root/include/pci.h
diff options
context:
space:
mode:
authorGavin Shan <gwshan@linux.vnet.ibm.com>2015-09-24 17:27:17 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-10-08 15:34:44 +1100
commit0c1cbc1667754037be40b1405ba30645598fe711 (patch)
tree84c89a6e9898c6a3b24299b93c48fc632fa36f30 /include/pci.h
parent37a74a4d1b0badee5b971a676b09bbf18ff816a4 (diff)
downloadskiboot-0c1cbc1667754037be40b1405ba30645598fe711.zip
skiboot-0c1cbc1667754037be40b1405ba30645598fe711.tar.gz
skiboot-0c1cbc1667754037be40b1405ba30645598fe711.tar.bz2
PCI: Introduce config register filter
We have to provide the emulated result for PCI config register access on some devices to eleminate the gap between hardware and software. One example would be the 0x28 (prefetchable memory window upper 32-bits) of the root complex on Naples isn't writable. Linux kernel relies on that to detect 64-bits window successfully. This introduces config register filter to PCI device to eleminate above gap. Each PCI device maintains a list of filters, which are populated when the PCI device is initialized. When PCI config space is accessed, the filter is searched to override the result from user (write) or hardware (read) if necessary. Reported-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com> Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Tested-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'include/pci.h')
-rw-r--r--include/pci.h28
1 files changed, 28 insertions, 0 deletions
diff --git a/include/pci.h b/include/pci.h
index 764ae5b..f74c961 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -90,6 +90,25 @@ struct pci_slot_info {
int slot_index;
};
+struct pci_device;
+struct pci_cfg_reg_filter;
+
+typedef void (*pci_cfg_reg_func)(struct pci_device *pd,
+ struct pci_cfg_reg_filter *pcrf,
+ uint32_t offset, uint32_t len,
+ uint32_t *data, bool write);
+struct pci_cfg_reg_filter {
+ uint32_t flags;
+#define PCI_REG_FLAG_READ 0x1
+#define PCI_REG_FLAG_WRITE 0x2
+#define PCI_REG_FLAG_MASK 0x3
+ uint32_t start;
+ uint32_t len;
+ uint8_t *data;
+ pci_cfg_reg_func func;
+ struct list_node link;
+};
+
/*
* While this might not be necessary in the long run, the existing
* Linux kernels expect us to provide a device-tree that contains
@@ -123,6 +142,10 @@ struct pci_device {
uint32_t cap[64];
uint32_t mps; /* Max payload size capability */
+ uint32_t pcrf_start;
+ uint32_t pcrf_end;
+ struct list_head pcrf;
+
struct pci_slot_info *slot_info;
struct pci_device *parent;
struct list_head children;
@@ -491,6 +514,11 @@ extern struct pci_device *pci_walk_dev(struct phb *phb,
void *userdata);
extern struct pci_device *pci_find_dev(struct phb *phb, uint16_t bdfn);
extern void pci_restore_bridge_buses(struct phb *phb);
+extern struct pci_cfg_reg_filter *pci_find_cfg_reg_filter(struct pci_device *pd,
+ uint32_t start, uint32_t len);
+extern struct pci_cfg_reg_filter *pci_add_cfg_reg_filter(struct pci_device *pd,
+ uint32_t start, uint32_t len,
+ uint32_t flags, pci_cfg_reg_func func);
/* Manage PHBs */
extern int64_t pci_register_phb(struct phb *phb, int opal_id);