diff options
author | Michael Brown <mcb30@ipxe.org> | 2022-08-08 16:39:40 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2022-08-08 16:39:40 +0100 |
commit | 0965cec53c9e421f900bb050b1c83196a0a5687b (patch) | |
tree | 4fa44fd1259f17fb9e40e299b51aadba09980f07 | |
parent | 9dfcdc04c86503924e1424757082d07e3649f59e (diff) | |
download | ipxe-0965cec53c9e421f900bb050b1c83196a0a5687b.tar.gz |
[pci] Generalise function-level reset mechanism
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/drivers/bus/pciextra.c | 22 | ||||
-rw-r--r-- | src/drivers/net/intelxlvf.c | 23 | ||||
-rw-r--r-- | src/include/ipxe/pci.h | 1 |
3 files changed, 26 insertions, 20 deletions
diff --git a/src/drivers/bus/pciextra.c b/src/drivers/bus/pciextra.c index 3082d8a3d..23617bc9a 100644 --- a/src/drivers/bus/pciextra.c +++ b/src/drivers/bus/pciextra.c @@ -1,6 +1,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdint.h> +#include <ipxe/timer.h> #include <ipxe/pci.h> static int pci_find_capability_common ( struct pci_device *pci, @@ -112,3 +113,24 @@ unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ) { size = size & ~( size - 1 ); return size; } + +/** + * Perform PCI Express function-level reset (FLR) + * + * @v pci PCI device + * @v exp PCI Express Capability address + */ +void pci_reset ( struct pci_device *pci, unsigned int exp ) { + uint16_t control; + + /* Perform a PCIe function-level reset */ + pci_read_config_word ( pci, ( exp + PCI_EXP_DEVCTL ), &control ); + control |= PCI_EXP_DEVCTL_FLR; + pci_write_config_word ( pci, ( exp + PCI_EXP_DEVCTL ), control ); + + /* Allow time for reset to complete */ + mdelay ( PCI_EXP_FLR_DELAY_MS ); + + /* Re-enable device */ + adjust_pci_device ( pci ); +} diff --git a/src/drivers/net/intelxlvf.c b/src/drivers/net/intelxlvf.c index 752de7815..b5957a53b 100644 --- a/src/drivers/net/intelxlvf.c +++ b/src/drivers/net/intelxlvf.c @@ -46,23 +46,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ /** - * Reset hardware via PCIe function-level reset - * - * @v intelxl Intel device - */ -static void intelxlvf_reset_flr ( struct intelxl_nic *intelxl, - struct pci_device *pci ) { - uint16_t control; - - /* Perform a PCIe function-level reset */ - pci_read_config_word ( pci, ( intelxl->exp + PCI_EXP_DEVCTL ), - &control ); - pci_write_config_word ( pci, ( intelxl->exp + PCI_EXP_DEVCTL ), - ( control | PCI_EXP_DEVCTL_FLR ) ); - mdelay ( INTELXL_RESET_DELAY_MS ); -} - -/** * Wait for admin event queue to be torn down * * @v intelxl Intel device @@ -637,7 +620,7 @@ static int intelxlvf_probe ( struct pci_device *pci ) { } /* Reset the function via PCIe FLR */ - intelxlvf_reset_flr ( intelxl, pci ); + pci_reset ( pci, intelxl->exp ); /* Enable MSI-X dummy interrupt */ if ( ( rc = intelxl_msix_enable ( intelxl, pci ) ) != 0 ) @@ -669,7 +652,7 @@ static int intelxlvf_probe ( struct pci_device *pci ) { err_open_admin: intelxl_msix_disable ( intelxl, pci ); err_msix: - intelxlvf_reset_flr ( intelxl, pci ); + pci_reset ( pci, intelxl->exp ); err_exp: iounmap ( intelxl->regs ); err_ioremap: @@ -701,7 +684,7 @@ static void intelxlvf_remove ( struct pci_device *pci ) { intelxl_msix_disable ( intelxl, pci ); /* Reset the function via PCIe FLR */ - intelxlvf_reset_flr ( intelxl, pci ); + pci_reset ( pci, intelxl->exp ); /* Free network device */ iounmap ( intelxl->regs ); diff --git a/src/include/ipxe/pci.h b/src/include/ipxe/pci.h index 933f48530..bf6174c23 100644 --- a/src/include/ipxe/pci.h +++ b/src/include/ipxe/pci.h @@ -309,6 +309,7 @@ extern int pci_find_capability ( struct pci_device *pci, int capability ); extern int pci_find_next_capability ( struct pci_device *pci, int pos, int capability ); extern unsigned long pci_bar_size ( struct pci_device *pci, unsigned int reg ); +extern void pci_reset ( struct pci_device *pci, unsigned int exp ); /** * Initialise PCI device |