[MTHCA] fixed card reset
authorleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 10 Apr 2006 09:34:51 +0000 (09:34 +0000)
committerleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 10 Apr 2006 09:34:51 +0000 (09:34 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@299 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

hw/mthca/kernel/hca_pci.c

index 083b9db..9efa74f 100644 (file)
@@ -273,19 +273,6 @@ __fixup_pci_capabilities(
 }\r
 \r
 \r
-#define PCI_CONFIG_OFFSET( field )                             \\r
-       offsetof( PCI_COMMON_CONFIG, field )\r
-\r
-#define PCI_CONFIG_LEN( fromField, toField )   \\r
-       offsetof( PCI_COMMON_CONFIG, toField ) -        \\r
-       offsetof( PCI_COMMON_CONFIG, fromField ) +      \\r
-       sizeof( ((PCI_COMMON_CONFIG*)NULL)->##toField )\r
-\r
-#define PCI_CONFIG_WRITE( fromField, toField )         \\r
-       pBusIfc->SetBusData( pBusIfc->Context, PCI_WHICHSPACE_CONFIG,           \\r
-       &pConfig->##fromField, PCI_CONFIG_OFFSET( fromField ),                  \\r
-       PCI_CONFIG_LEN( fromField, toField ) )\r
-\r
 /*\r
  * Restore saved PCI configuration, skipping registers 22 and 23, as well\r
  * as any registers where writing will have side effects such as the flags\r
@@ -298,84 +285,36 @@ __restore_pci_config(
        IN                              BUS_INTERFACE_STANDARD          *pBusIfc,\r
        IN                              PCI_COMMON_CONFIG* const        pConfig )\r
 {\r
-       ULONG                                           len;\r
-       UCHAR                                           *pBuf;\r
+       NTSTATUS status = STATUS_SUCCESS;\r
+       int             i, *pci_hdr = (int*)pConfig;\r
 \r
        HCA_ENTER( HCA_DBG_PNP );\r
 \r
-       pBuf = (UCHAR*)pConfig;\r
-\r
-       /* Fixup the capabilities as needed. */\r
-       __fixup_pci_capabilities( pConfig );\r
-\r
-       /* Restore the vendor/device IDs */\r
-       len = PCI_CONFIG_WRITE( VendorID, DeviceID );\r
-       if( len != PCI_CONFIG_LEN( VendorID, DeviceID ) )\r
-       {\r
-               HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("Failed to write vendor/device IDs.\n"));\r
-               return STATUS_DEVICE_NOT_READY;\r
-       }\r
-\r
-       /*\r
-        * Skip the command register and write the rest (except the bridge\r
-        * control if this is a bridge).\r
-        */\r
-       if( pConfig->HeaderType == PCI_DEVICE_TYPE )\r
-       {\r
-               len = PCI_CONFIG_WRITE( Status, u.type0.MaximumLatency );\r
-               if( len != PCI_CONFIG_LEN( Status, u.type0.MaximumLatency ) )\r
-               {\r
-                       HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("Failed to write type 0 common header.\n"));\r
-                       return STATUS_DEVICE_NOT_READY;\r
-               }\r
-       }\r
-       else\r
-       {\r
-               ASSERT( pConfig->HeaderType == PCI_BRIDGE_TYPE );\r
-               len = PCI_CONFIG_WRITE( Status, u.type1.InterruptPin );\r
-               if( len != PCI_CONFIG_LEN( Status, u.type1.InterruptPin ) )\r
-               {\r
-                       HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("Failed to write type 1 common header.\n"));\r
-                       return STATUS_DEVICE_NOT_READY;\r
+       for (i = 0; i < 16; ++i) {\r
+               if (i == 1)\r
+                       continue;\r
+       \r
+               if (4 != pBusIfc->SetBusData( pBusIfc->Context,\r
+                       PCI_WHICHSPACE_CONFIG, &pci_hdr[i], i * 4, 4 )) {\r
+                       HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,\r
+                               ("Couldn't restore PCI cfg reg %x,   aborting.\n", i));\r
+                       status =  STATUS_DEVICE_NOT_READY;\r
+                       goto out;\r
                }\r
        }\r
 \r
-       /* Write the capabilities back. */\r
-       len = pBusIfc->SetBusData( pBusIfc->Context, PCI_WHICHSPACE_CONFIG,\r
-               pConfig->DeviceSpecific, PCI_CONFIG_OFFSET( DeviceSpecific ), 192 );\r
-       if( len != 192 )\r
-       {\r
-               HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("Failed to write capabilites.\n"));\r
-               return STATUS_DEVICE_NOT_READY;\r
-       }\r
-\r
        /* Write the command register. */\r
-       len = PCI_CONFIG_WRITE( Command, Command );\r
-       if( len != PCI_CONFIG_LEN( Command, Command ) )\r
-       {\r
-               HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_SHIM  ,("Failed to write command register.\n"));\r
-               return STATUS_DEVICE_NOT_READY;\r
-       }\r
-\r
-       /* Write the bridge control register if a bridge. */\r
-       if( pConfig->HeaderType == PCI_BRIDGE_TYPE )\r
-       {\r
-               len =\r
-                       PCI_CONFIG_WRITE( u.type1.BridgeControl, u.type1.BridgeControl );\r
-               if( len !=\r
-                       PCI_CONFIG_LEN( u.type1.BridgeControl, u.type1.BridgeControl ) )\r
-               {\r
-                       HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
-                               ("Failed to write bridge control register.\n"));\r
-                       return STATUS_DEVICE_NOT_READY;\r
-               }\r
+       if (4 != pBusIfc->SetBusData( pBusIfc->Context,\r
+               PCI_WHICHSPACE_CONFIG, &pci_hdr[1], 4, 4 )) {\r
+               HCA_PRINT( TRACE_LEVEL_ERROR ,HCA_DBG_PNP ,("Couldn't restore COMMAND.\n"));\r
+               status =  STATUS_DEVICE_NOT_READY;\r
        }\r
 \r
+out:   \r
        HCA_EXIT( HCA_DBG_PNP );\r
-       return STATUS_SUCCESS;\r
+       return status;\r
 }\r
 \r
-\r
 NTSTATUS\r
 hca_reset( DEVICE_OBJECT* const                pDevObj, int is_tavor )\r
 {\r
@@ -384,165 +323,118 @@ hca_reset( DEVICE_OBJECT* const         pDevObj, int is_tavor )
        BUS_INTERFACE_STANDARD  hcaBusIfc;\r
        BUS_INTERFACE_STANDARD  brBusIfc = {0}; // to bypass C4701\r
        hca_dev_ext_t                   *pExt = (hca_dev_ext_t*)pDevObj->DeviceExtension;\r
-       ULONG                                   data, i;\r
-       PULONG  reset_p;\r
-       PHYSICAL_ADDRESS  pa;\r
-       static int skip = 1;\r
 \r
        HCA_ENTER( HCA_DBG_PNP );\r
-       if (skip) goto resetErr1;\r
 \r
-       /* Get the HCA's bus interface. */\r
-       status = __get_bus_ifc( pDevObj, &GUID_BUS_INTERFACE_STANDARD, &hcaBusIfc );\r
-       if( !NT_SUCCESS( status ) )\r
+       /* get the resources */\r
        {\r
-               HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_SHIM  ,("Failed to get HCA bus interface.\n"));\r
-               goto resetErr1;\r
-       }\r
+               /* Get the HCA's bus interface. */\r
+               status = __get_bus_ifc( pDevObj, &GUID_BUS_INTERFACE_STANDARD, &hcaBusIfc );\r
+               if( !NT_SUCCESS( status ) ) {\r
+                       HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_SHIM  ,("Failed to get HCA bus interface.\n"));\r
+                       goto resetErr1;\r
+               }\r
 \r
-       if (is_tavor) {\r
-#ifdef WIN_TO_BE_REMOVED\r
-               /* Get the HCA Bridge's bus interface. */\r
-               status = __get_bus_ifc( pDevObj, &GUID_HCA_BRIDGE_INTERFACE, &brBusIfc );\r
-               if( !NT_SUCCESS( status ) )\r
-               {\r
-                       HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
-                               ("Failed to get HCA bridge bus interface.\n"));\r
-                       goto resetErr2;\r
+               /* Get the HCA Bridge's bus interface, if any */\r
+               if (is_tavor) {\r
+                       if (!FindBridgeIf( pExt, &brBusIfc ))\r
+                               goto resetErr2;\r
                }\r
-#else\r
-               if (!FindBridgeIf( pExt, &brBusIfc ))\r
-                       goto resetErr2;\r
-#endif\r
        }\r
 \r
-       /* Save the HCA's configuration. */\r
-       status = __save_pci_config( &hcaBusIfc, &hcaConfig );\r
-       if( !NT_SUCCESS( status ) )\r
+       /* Save the HCA's PCI configuration headers */\r
        {\r
-               HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,\r
-                       ("Failed to save HCA config.\n"));\r
-               goto resetErr3;\r
-       }\r
-\r
-       if (is_tavor) {\r
-               /* Save the HCA bridge's configuration. */\r
-               status = __save_pci_config( &brBusIfc, &brConfig );\r
-               if( !NT_SUCCESS( status ) )\r
-               {\r
+               status = __save_pci_config( &hcaBusIfc, &hcaConfig );\r
+               if( !NT_SUCCESS( status ) ) {\r
                        HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,\r
-                               ("Failed to save bridge config.\n"));\r
+                               ("Failed to save HCA config.\n"));\r
                        goto resetErr3;\r
                }\r
+\r
+               /* Save the HCA bridge's configuration, if any */\r
+               if (is_tavor) {\r
+                       status = __save_pci_config( &brBusIfc, &brConfig );\r
+                       if( !NT_SUCCESS( status ) ) {\r
+                               HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP,\r
+                                       ("Failed to save bridge config.\n"));\r
+                               goto resetErr3;\r
+                       }\r
+               }\r
        }\r
        \r
-       /* map reset register */\r
-       pa.QuadPart = pExt->bar[HCA_BAR_TYPE_HCR].phys + HCA_RESET_HCR_OFFSET;\r
-       HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP  ,("Mapping reset register with address 0x%I64x\n", pa.QuadPart));\r
-       reset_p = MmMapIoSpace( pa,     4, MmNonCached );\r
-       if( !reset_p )\r
+       /* reset the card */\r
        {\r
-               HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("Failed to map reset register with address 0x%I64x\n", pa.QuadPart));\r
-               status = STATUS_UNSUCCESSFUL;\r
-               goto resetErr3;\r
-       }\r
-       \r
-       /* Issue the reset. */\r
-       HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP  ,("Resetting  the chip ...\n"));\r
-       WRITE_REGISTER_ULONG( reset_p, HCA_RESET_TOKEN );\r
+               PULONG  reset_p;\r
+               PHYSICAL_ADDRESS  pa;\r
+               /* map reset register */\r
+               pa.QuadPart = pExt->bar[HCA_BAR_TYPE_HCR].phys + (uint64_t)HCA_RESET_HCR_OFFSET;\r
+               HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP  ,("Mapping reset register with address 0x%I64x\n", pa.QuadPart));\r
+               reset_p = MmMapIoSpace( pa,     4, MmNonCached );\r
+               if( !reset_p ) {\r
+                       HCA_PRINT( TRACE_LEVEL_ERROR  ,HCA_DBG_PNP  ,("Failed to map reset register with address 0x%I64x\n", pa.QuadPart));\r
+                       status = STATUS_UNSUCCESSFUL;\r
+                       goto resetErr3;\r
+               }\r
+               \r
+               /* Issue the reset. */\r
+               HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP  ,("Resetting  the chip ...\n"));\r
+               WRITE_REGISTER_ULONG( reset_p, HCA_RESET_TOKEN );\r
 \r
-       /* Wait a second. */\r
-       cl_thread_suspend( 1000 );\r
+               /* unmap the reset register */\r
+               HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP  ,("Unmapping reset register \n"));\r
+               MmUnmapIoSpace( reset_p, 4 );\r
 \r
-       /* unmap the reset register */\r
-       HCA_PRINT( TRACE_LEVEL_INFORMATION ,HCA_DBG_PNP  ,("Unmapping reset register \n"));\r
-       MmUnmapIoSpace( reset_p, 4 );\r
+               /* Wait a second. */\r
+               cl_thread_suspend( 1000 );\r
+       }\r
 \r
-       \r
-       if (is_tavor) {\r
-               /*\r
-                * Now read the bridge's configuration register until it doesn't\r
-                * return 0xFFFFFFFF.  Give it 10 seconds for good measure.\r
-                */\r
-               HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP  ,("Read the Bridge's configuration register \n"));\r
-               for( i = 0; i < 10; i++ )\r
-               {\r
-                       if( brBusIfc.GetBusData( brBusIfc.Context, PCI_WHICHSPACE_CONFIG,\r
-                               &data, 0, sizeof(ULONG) ) != sizeof(ULONG) )\r
-                       {\r
+       /* Read the configuration register until it doesn't return 0xFFFFFFFF */\r
+       {\r
+               ULONG                                   data, i;\r
+               BUS_INTERFACE_STANDARD *p_ifc = (is_tavor) ? &brBusIfc : &hcaBusIfc;\r
+               HCA_PRINT( TRACE_LEVEL_INFORMATION      ,HCA_DBG_PNP  ,("Read the configuration register \n"));\r
+               for( i = 0; i < 100; i++ ) {\r
+                       if (4 != p_ifc->GetBusData( p_ifc->Context,\r
+                               PCI_WHICHSPACE_CONFIG, &data, 0, 4)) {\r
                                HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
-                                       ("Failed to read bridge configuration data.\n"));\r
+                                       ("Failed to read device configuration data.\n"));\r
                                status = STATUS_UNSUCCESSFUL;\r
                                goto resetErr3;\r
                        }\r
                        /* See if we got valid data. */\r
                        if( data != 0xFFFFFFFF )\r
-                               break;\r
-\r
-                       cl_thread_suspend( 1000 );\r
+                               goto good;\r
+               \r
+                       cl_thread_suspend( 100 );\r
                }       \r
-               if( i == 10 )\r
-               {\r
-                       /* Darn, timed out. :( */\r
-                       HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
-                               ("Doh! HCA Bridge never came back from reset!\n"));\r
-                       status = STATUS_UNSUCCESSFUL;\r
-                       goto resetErr3;\r
-               }\r
-       }       \r
-\r
-       else {\r
-               /*\r
-                * Now read the HCA's configuration register until it doesn't\r
-                * return 0xFFFFFFFF.  Give it 10 seconds for good measure.\r
-                */\r
-               HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP  ,("Read the HCA's configuration register \n"));\r
-               for( i = 0; i < 100; i++ )\r
-               {\r
-                       if( hcaBusIfc.GetBusData( hcaBusIfc.Context, PCI_WHICHSPACE_CONFIG,\r
-                               &data, 0, sizeof(ULONG) ) != sizeof(ULONG) )\r
-                       {\r
+\r
+               HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
+                       ("Doh! PCI device did not come back after reset!\n"));\r
+               status = STATUS_UNSUCCESSFUL;\r
+               goto resetErr3;\r
+       }\r
+\r
+good:  /* restore the HCA's PCI configuration headers */\r
+       {\r
+               if (is_tavor) {\r
+                       /* Restore the HCA's bridge configuration. */\r
+                       HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP  ,("Restoring bridge PCI configuration \n"));\r
+                       status = __restore_pci_config( &brBusIfc, &brConfig );\r
+                       if( !NT_SUCCESS( status ) ) {\r
                                HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
-                                       ("Failed to read HCA configuration data.\n"));\r
-                               status = STATUS_UNSUCCESSFUL;\r
+                                       ("Failed to restore bridge config.\n"));\r
                                goto resetErr3;\r
                        }\r
-                       /* See if we got valid data. */\r
-                       if( data != 0xFFFFFFFF )\r
-                               break;\r
-\r
-                       cl_thread_suspend( 100 );\r
-               } \r
-               if( i >= 100 )\r
-               {\r
-                       /* Darn, timed out. :( */\r
-                       HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
-                               ("Doh! HCA Bridge never came back from reset!\n"));\r
-                       status = STATUS_UNSUCCESSFUL;\r
-                       goto resetErr3;\r
                }\r
-       }\r
-       \r
-       if (is_tavor) {\r
-               /* Restore the HCA's bridge configuration. */\r
-               HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP  ,("Restoring bridge PCI configuration \n"));\r
-               status = __restore_pci_config( &brBusIfc, &brConfig );\r
-               if( !NT_SUCCESS( status ) )\r
-               {\r
+               \r
+               /* Restore the HCA's configuration. */\r
+               HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP  ,("Restoring HCA PCI configuration \n"));\r
+               status = __restore_pci_config( &hcaBusIfc, &hcaConfig );\r
+               if( !NT_SUCCESS( status ) ) {\r
                        HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
-                               ("Failed to restore bridge config.\n"));\r
-                       goto resetErr3;\r
+                               ("Failed to restore HCA config.\n"));\r
                }\r
        }\r
-       \r
-       /* Restore the HCA's configuration. */\r
-       HCA_PRINT( TRACE_LEVEL_INFORMATION  ,HCA_DBG_PNP  ,("Restoring HCA PCI configuration \n"));\r
-       status = __restore_pci_config( &hcaBusIfc, &hcaConfig );\r
-       if( !NT_SUCCESS( status ) )\r
-       {\r
-               HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_PNP, \r
-                       ("Failed to restore HCA config.\n"));\r
-       }\r
 \r
 resetErr3:\r
        if (is_tavor) \r