[pci] Allow pci_find_next() to return non-zero PCI segments

Separate the return status code from the returned PCI bus:dev.fn
address, in order to allow pci_find_next() to be used to find devices
with a non-zero PCI segment number.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/583/merge
Michael Brown 2022-09-15 14:55:26 +01:00
parent 6459e3b7b1
commit 8fc3c26eae
3 changed files with 14 additions and 16 deletions

View File

@ -229,9 +229,10 @@ int pci_read_config ( struct pci_device *pci ) {
* *
* @v pci PCI device to fill in * @v pci PCI device to fill in
* @v busdevfn Starting bus:dev.fn address * @v busdevfn Starting bus:dev.fn address
* @ret busdevfn Bus:dev.fn address of next PCI device, or negative error * @ret busdevfn Bus:dev.fn address of next PCI device
* @ret rc Return status code
*/ */
int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ) { int pci_find_next ( struct pci_device *pci, uint32_t *busdevfn ) {
static unsigned int end; static unsigned int end;
unsigned int sub_end; unsigned int sub_end;
uint8_t hdrtype; uint8_t hdrtype;
@ -243,11 +244,11 @@ int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ) {
end = PCI_BUSDEVFN ( 0, pci_num_bus(), 0, 0 ); end = PCI_BUSDEVFN ( 0, pci_num_bus(), 0, 0 );
/* Find next PCI device, if any */ /* Find next PCI device, if any */
for ( ; busdevfn < end ; busdevfn++ ) { for ( ; *busdevfn < end ; (*busdevfn)++ ) {
/* Check for PCI device existence */ /* Check for PCI device existence */
memset ( pci, 0, sizeof ( *pci ) ); memset ( pci, 0, sizeof ( *pci ) );
pci_init ( pci, busdevfn ); pci_init ( pci, *busdevfn );
if ( ( rc = pci_read_config ( pci ) ) != 0 ) if ( ( rc = pci_read_config ( pci ) ) != 0 )
continue; continue;
@ -267,7 +268,7 @@ int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ) {
} }
/* Return this device */ /* Return this device */
return busdevfn; return 0;
} }
return -ENODEV; return -ENODEV;
@ -348,7 +349,7 @@ void pci_remove ( struct pci_device *pci ) {
*/ */
static int pcibus_probe ( struct root_device *rootdev ) { static int pcibus_probe ( struct root_device *rootdev ) {
struct pci_device *pci = NULL; struct pci_device *pci = NULL;
int busdevfn = 0; uint32_t busdevfn = 0;
int rc; int rc;
for ( busdevfn = 0 ; 1 ; busdevfn++ ) { for ( busdevfn = 0 ; 1 ; busdevfn++ ) {
@ -362,8 +363,7 @@ static int pcibus_probe ( struct root_device *rootdev ) {
} }
/* Find next PCI device, if any */ /* Find next PCI device, if any */
busdevfn = pci_find_next ( pci, busdevfn ); if ( ( rc = pci_find_next ( pci, &busdevfn ) ) != 0 )
if ( busdevfn < 0 )
break; break;
/* Look for a driver */ /* Look for a driver */

View File

@ -58,7 +58,7 @@ static int pciscan_exec ( int argc, char **argv ) {
struct named_setting setting; struct named_setting setting;
struct pci_device pci; struct pci_device pci;
unsigned long prev; unsigned long prev;
int next; uint32_t busdevfn;
int len; int len;
int rc; int rc;
@ -75,17 +75,15 @@ static int pciscan_exec ( int argc, char **argv ) {
if ( ( len = fetchn_setting ( setting.settings, &setting.setting, if ( ( len = fetchn_setting ( setting.settings, &setting.setting,
NULL, &setting.setting, &prev ) ) < 0 ) { NULL, &setting.setting, &prev ) ) < 0 ) {
/* Setting not yet defined: start searching from 00:00.0 */ /* Setting not yet defined: start searching from 00:00.0 */
prev = 0; busdevfn = 0;
} else { } else {
/* Setting is defined: start searching from next location */ /* Setting is defined: start searching from next location */
prev++; busdevfn = ( prev + 1 );
} }
/* Find next existent PCI device */ /* Find next existent PCI device */
if ( ( next = pci_find_next ( &pci, prev ) ) < 0 ) { if ( ( rc = pci_find_next ( &pci, &busdevfn ) ) != 0 )
rc = next;
goto err_find_next; goto err_find_next;
}
/* Apply default type if necessary. Use ":uint16" rather than /* Apply default type if necessary. Use ":uint16" rather than
* ":busdevfn" to allow for easy inclusion within a * ":busdevfn" to allow for easy inclusion within a
@ -96,7 +94,7 @@ static int pciscan_exec ( int argc, char **argv ) {
/* Store setting */ /* Store setting */
if ( ( rc = storen_setting ( setting.settings, &setting.setting, if ( ( rc = storen_setting ( setting.settings, &setting.setting,
next ) ) != 0 ) { busdevfn ) ) != 0 ) {
printf ( "Could not store \"%s\": %s\n", printf ( "Could not store \"%s\": %s\n",
setting.setting.name, strerror ( rc ) ); setting.setting.name, strerror ( rc ) );
goto err_store; goto err_store;

View File

@ -301,7 +301,7 @@ extern void adjust_pci_device ( struct pci_device *pci );
extern unsigned long pci_bar_start ( struct pci_device *pci, extern unsigned long pci_bar_start ( struct pci_device *pci,
unsigned int reg ); unsigned int reg );
extern int pci_read_config ( struct pci_device *pci ); extern int pci_read_config ( struct pci_device *pci );
extern int pci_find_next ( struct pci_device *pci, unsigned int busdevfn ); extern int pci_find_next ( struct pci_device *pci, uint32_t *busdevfn );
extern int pci_find_driver ( struct pci_device *pci ); extern int pci_find_driver ( struct pci_device *pci );
extern int pci_probe ( struct pci_device *pci ); extern int pci_probe ( struct pci_device *pci );
extern void pci_remove ( struct pci_device *pci ); extern void pci_remove ( struct pci_device *pci );