From 9f7141a1cedeca6d55b9ce43322f509a4577c883 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 14 Oct 2009 02:09:49 +0100 Subject: [PATCH] [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 --- src/drivers/infiniband/hermon.c | 23 +++++++++++++++++++++++ src/drivers/infiniband/hermon.h | 5 +++++ 2 files changed, 28 insertions(+) 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 #include #include +#include #include #include #include @@ -2550,6 +2551,25 @@ static int hermon_configure_special_qps ( struct hermon *hermon ) { return 0; } +/** + * 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 * @@ -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