pci: Add support for filtering by function

This will be useful for PCI based drivers to integrate fully within
the device driver model, where they will have to provide the function
they are found.

Change-Id: I7d64a4c6727cee52cbcb743c859cda43ac1a853b
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2015-08-21 12:52:25 +03:00 committed by Anas Nashif
commit ff39559146
5 changed files with 48 additions and 15 deletions

View file

@ -65,6 +65,7 @@ the 'ia32_pci' platform.
/* Generic definitions */
#define CONFIG_UART_PCI_VENDOR_ID 0x8086
#define CONFIG_UART_PCI_DEVICE_ID 0x0936
#define CONFIG_UART_PCI_FUNCTION PCI_FUNCTION_ANY
#define CONFIG_UART_PCI_BAR 0
#define CONFIG_UART_BAUDRATE COM1_BAUD_RATE

View file

@ -110,6 +110,7 @@ static int ia32_pci_init(struct device *arg)
#ifdef CONFIG_PCI_DEBUG
/* Rescan PCI and display the list of PCI attached devices */
struct pci_dev_info info = {
.function = PCI_FUNCTION_ANY,
.bar = PCI_BAR_ANY,
};
@ -120,6 +121,7 @@ static int ia32_pci_init(struct device *arg)
info.class = 0;
info.vendor_id = 0;
info.device_id = 0;
info.function = PCI_FUNCTION_ANY;
info.bar = PCI_BAR_ANY;
}
#endif /* CONFIG_PCI_DEBUG */

View file

@ -129,7 +129,7 @@ restarting from 0.
/* NOTE. These parameters may need to be configurable */
#define LSPCI_MAX_BUS PCI_BUS_NUMBERS /* maximum number of buses to scan */
#define LSPCI_MAX_DEV 32 /* maximum number of devices to scan */
#define LSPCI_MAX_FUNC 8 /* maximum device functions to scan */
#define LSPCI_MAX_FUNC PCI_MAX_FUNCTIONS /* maximum functions to scan */
#define LSPCI_MAX_REG 64 /* maximum device registers to read */
/* Base Address Register configuration fields */
@ -279,9 +279,8 @@ static inline int pci_dev_scan(union pci_addr_reg pci_ctrl_addr,
uint32_t pci_data;
int max_bars;
/* scan all the possible functions for this device */
for (; lookup.func < LSPCI_MAX_FUNC; lookup.bar = 0, lookup.func++) {
pci_ctrl_addr.field.func = lookup.func;
/* verify first if there is a valid device at this point */
pci_ctrl_addr.field.func = 0;
pci_read(DEFAULT_PCI_CONTROLLER,
pci_ctrl_addr,
@ -289,12 +288,28 @@ static inline int pci_dev_scan(union pci_addr_reg pci_ctrl_addr,
&pci_data);
if (pci_data == 0xffffffff) {
if (lookup.func == 0) {
return 0;
}
/* scan all the possible functions for this device */
for (; lookup.func < LSPCI_MAX_FUNC; lookup.bar = 0, lookup.func++) {
if (lookup.info.function != PCI_FUNCTION_ANY &&
lookup.func != lookup.info.function) {
return 0;
}
pci_ctrl_addr.field.func = lookup.func;
if (lookup.func != 0) {
pci_read(DEFAULT_PCI_CONTROLLER,
pci_ctrl_addr,
sizeof(pci_data),
&pci_data);
if (pci_data == 0xffffffff) {
continue;
}
}
/* get the PCI header from the device */
pci_header_get(DEFAULT_PCI_CONTROLLER,
@ -367,6 +382,7 @@ void pci_bus_scan_init(void)
lookup.info.class = 0;
lookup.info.vendor_id = 0;
lookup.info.device_id = 0;
lookup.info.function = PCI_FUNCTION_ANY;
lookup.info.bar = PCI_BAR_ANY;
lookup.bus = 0;
lookup.dev = 0;
@ -395,10 +411,12 @@ int pci_bus_scan(struct pci_dev_info *dev_info)
if (!lookup.info.class &&
!lookup.info.vendor_id &&
!lookup.info.device_id &&
lookup.info.bar == PCI_BAR_ANY) {
lookup.info.bar == PCI_BAR_ANY &&
lookup.info.function == PCI_FUNCTION_ANY) {
lookup.info.class = dev_info->class;
lookup.info.vendor_id = dev_info->vendor_id;
lookup.info.device_id = dev_info->device_id;
lookup.info.function = dev_info->function;
lookup.info.bar = dev_info->bar;
if (class_bd[lookup.info.class].set) {
@ -411,16 +429,25 @@ int pci_bus_scan(struct pci_dev_info *dev_info)
pci_ctrl_addr.value = 0;
pci_ctrl_addr.field.enable = 1;
if (lookup.info.function != PCI_FUNCTION_ANY) {
lookup.func = lookup.info.function;
}
/* run through the buses and devices */
for (; lookup.bus < LSPCI_MAX_BUS; lookup.bus++) {
for (; (lookup.dev < LSPCI_MAX_DEV);
lookup.func = 0, lookup.dev++) {
for (; (lookup.dev < LSPCI_MAX_DEV); lookup.dev++) {
pci_ctrl_addr.field.bus = lookup.bus;
pci_ctrl_addr.field.device = lookup.dev;
if (pci_dev_scan(pci_ctrl_addr, dev_info)) {
return 1;
}
if (lookup.info.function != PCI_FUNCTION_ANY) {
lookup.func = lookup.info.function;
} else {
lookup.func = 0;
}
}
}

View file

@ -226,6 +226,7 @@ static inline void ns16550_pci_uart_scan(void)
.class = PCI_CLASS_COMM_CTLR,
.vendor_id = CONFIG_UART_PCI_VENDOR_ID,
.device_id = CONFIG_UART_PCI_DEVICE_ID,
.function = CONFIG_UART_PCI_FUNCTION,
.bar = CONFIG_UART_PCI_BAR,
};
int i;

View file

@ -41,6 +41,9 @@ Module declares routines of PCI bus initialization and query
#define BAR_SPACE_MEM 0
#define BAR_SPACE_IO 1
#define PCI_MAX_FUNCTIONS 8
#define PCI_FUNCTION_ANY PCI_MAX_FUNCTIONS
#define PCI_MAX_BARS 6
#define PCI_BAR_ANY PCI_MAX_BARS
@ -52,9 +55,8 @@ struct pci_dev_info {
int irq;
uint16_t mem_type:1; /* memory type: BAR_SPACE_MEM/BAR_SPACE_IO */
uint16_t class:8;
uint16_t function:3;
uint16_t function:4;
uint16_t bar:3;
uint16_t unused:1;
uint16_t vendor_id;
uint16_t device_id;
};