diff options
author | Michael Brown <mcb30@etherboot.org> | 2009-10-14 02:09:49 +0100 |
---|---|---|
committer | Michael Brown <mcb30@etherboot.org> | 2009-10-14 02:11:16 +0100 |
commit | 9f7141a1cedeca6d55b9ce43322f509a4577c883 (patch) | |
tree | e2a90b24905305267a83904747643ebec171191d | |
parent | 4175b778c277c87980266c854139b7f93b5564d9 (diff) | |
download | ipxe-9f7141a1cedeca6d55b9ce43322f509a4577c883.tar.gz |
[hermon] Reset device during probe()
Some systems will retry their boot sequence in the event of a boot
failure. On these systems, the second and subsequent boot attempts
will fail to initialise the Hermon HCA.
Fix by resetting the HCA during probe(). This incurs a one-second
cost, but there seems to be no viable alternative.
Originally-fixed-by: Itay Gazit <itaygazit@gmail.com>
-rw-r--r-- | src/drivers/infiniband/hermon.c | 23 | ||||
-rw-r--r-- | src/drivers/infiniband/hermon.h | 5 |
2 files changed, 28 insertions, 0 deletions
diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c index bff128fd..b9c97f94 100644 --- a/src/drivers/infiniband/hermon.c +++ b/src/drivers/infiniband/hermon.c @@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include <byteswap.h> #include <gpxe/io.h> #include <gpxe/pci.h> +#include <gpxe/pcibackup.h> #include <gpxe/malloc.h> #include <gpxe/umalloc.h> #include <gpxe/iobuf.h> @@ -2551,6 +2552,25 @@ static int hermon_configure_special_qps ( struct hermon *hermon ) { } /** + * Reset device + * + * @v hermon Hermon device + * @v pci PCI device + */ +static void hermon_reset ( struct hermon *hermon, + struct pci_device *pci ) { + struct pci_config_backup backup; + static const uint8_t backup_exclude[] = + PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c ); + + pci_backup ( pci, &backup, backup_exclude ); + writel ( HERMON_RESET_MAGIC, + ( hermon->config + HERMON_RESET_OFFSET ) ); + mdelay ( HERMON_RESET_WAIT_TIME_MS ); + pci_restore ( pci, &backup, backup_exclude ); +} + +/** * Probe PCI device * * @v pci PCI device @@ -2582,6 +2602,9 @@ static int hermon_probe ( struct pci_device *pci, hermon->uar = ioremap ( pci_bar_start ( pci, HERMON_PCI_UAR_BAR ), HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE ); + /* Reset device */ + hermon_reset ( hermon, pci ); + /* Allocate space for mailboxes */ hermon->mailbox_in = malloc_dma ( HERMON_MBOX_SIZE, HERMON_MBOX_ALIGN ); diff --git a/src/drivers/infiniband/hermon.h b/src/drivers/infiniband/hermon.h index f19fd359..c53f3da5 100644 --- a/src/drivers/infiniband/hermon.h +++ b/src/drivers/infiniband/hermon.h @@ -29,6 +29,11 @@ FILE_LICENCE ( GPL2_OR_LATER ); #define HERMON_PCI_CONFIG_BAR_SIZE 0x100000 #define HERMON_PCI_UAR_BAR PCI_BASE_ADDRESS_2 +/* Device reset */ +#define HERMON_RESET_OFFSET 0x0f0010 +#define HERMON_RESET_MAGIC 0x01000000UL +#define HERMON_RESET_WAIT_TIME_MS 1000 + /* Work queue entry and completion queue entry opcodes */ #define HERMON_OPCODE_NOP 0x00 #define HERMON_OPCODE_SEND 0x0a |