diff options
author | Gavin Shan <gwshan@linux.vnet.ibm.com> | 2015-09-24 17:27:17 +1000 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2015-10-08 15:34:44 +1100 |
commit | 0c1cbc1667754037be40b1405ba30645598fe711 (patch) | |
tree | 84c89a6e9898c6a3b24299b93c48fc632fa36f30 /include/pci.h | |
parent | 37a74a4d1b0badee5b971a676b09bbf18ff816a4 (diff) | |
download | skiboot-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.h | 28 |
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); |