]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[hermon] Minimise reset time 245/head
authorMichael Brown <mcb30@ipxe.org>
Mon, 1 Feb 2021 22:25:52 +0000 (22:25 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 1 Feb 2021 22:29:30 +0000 (22:29 +0000)
Check for reset completion by waiting for the device to respond to PCI
configuration cycles, as documented in the Programmer's Reference
Manual.  On the original ConnectX HCA, this reduces the time spent on
reset from 1000ms down to 1ms.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/infiniband/hermon.c
src/drivers/infiniband/hermon.h

index 35326ac6e896e6a164986df8f245a714a0114431..d13a14678f6175c5fcb3158330cf3afc822c38e3 100644 (file)
@@ -2792,22 +2792,45 @@ static void hermon_unmap_icm ( struct hermon *hermon ) {
  * Reset device
  *
  * @v hermon           Hermon device
+ * @ret rc             Return status code
  */
-static void hermon_reset ( struct hermon *hermon ) {
+static int hermon_reset ( struct hermon *hermon ) {
        struct pci_device *pci = hermon->pci;
        struct pci_config_backup backup;
        static const uint8_t backup_exclude[] =
                PCI_CONFIG_BACKUP_EXCLUDE ( 0x58, 0x5c );
+       uint16_t vendor;
+       unsigned int i;
+
+       /* Reset command interface toggle */
+       hermon->toggle = 0;
 
        /* Perform device reset and preserve PCI configuration */
        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 );
 
-       /* Reset command interface toggle */
-       hermon->toggle = 0;
+       /* Wait until device starts responding to configuration cycles */
+       for ( i = 0 ; i < HERMON_RESET_MAX_WAIT_MS ; i++ ) {
+
+               /* Read PCI vendor ID */
+               pci_read_config_word ( pci, PCI_VENDOR_ID, &vendor );
+               if ( vendor == pci->vendor ) {
+
+                       /* Restore PCI configuration */
+                       pci_restore ( pci, &backup, backup_exclude );
+
+                       DBGC ( hermon, "Hermon %p reset after %dms\n",
+                              hermon, i );
+                       return 0;
+               }
+
+               /* Delay */
+               mdelay ( 1 );
+       }
+
+       DBGC ( hermon, "Hermon %p timed out waiting for reset\n", hermon );
+       return -ETIMEDOUT;
 }
 
 /**
@@ -3967,7 +3990,8 @@ static int hermon_probe ( struct pci_device *pci ) {
                                    HERMON_UAR_NON_EQ_PAGE * HERMON_PAGE_SIZE );
 
        /* Reset device */
-       hermon_reset ( hermon );
+       if ( ( rc = hermon_reset ( hermon ) ) != 0 )
+               goto err_reset;
 
        /* Start firmware */
        if ( ( rc = hermon_start_firmware ( hermon ) ) != 0 )
@@ -4060,6 +4084,7 @@ static int hermon_probe ( struct pci_device *pci ) {
  err_get_cap:
        hermon_stop_firmware ( hermon );
  err_start_firmware:
+ err_reset:
        iounmap ( hermon->uar );
        iounmap ( hermon->config );
        hermon_free ( hermon );
index fddd7fd416fad2e28cbbe6ef95e8336bdcfdbd4e..a952bbd8158d0988c32502c353693eba4ded2c81 100644 (file)
@@ -35,7 +35,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 /* Device reset */
 #define HERMON_RESET_OFFSET            0x0f0010
 #define HERMON_RESET_MAGIC             0x01000001UL
-#define HERMON_RESET_WAIT_TIME_MS      1000
+#define HERMON_RESET_MAX_WAIT_MS       1000
 
 /* Work queue entry and completion queue entry opcodes */
 #define HERMON_OPCODE_NOP              0x00