]> git.karo-electronics.de Git - linux-beck.git/commitdiff
staging/rdma/hfi1: Fix fabric serdes reset by re-downloading firmware
authorDean Luick <dean.luick@intel.com>
Wed, 3 Feb 2016 22:35:40 +0000 (14:35 -0800)
committerDoug Ledford <dledford@redhat.com>
Fri, 11 Mar 2016 01:37:56 +0000 (20:37 -0500)
A host fabric serdes reset is required to go back to polling.
However, access to the fabric serdes may have been invalidated
by the sibling HFI when it downloads its fabric serdes firmware.
Work around this by re-downloading and re-validating the serdes
firmware at reset time on Bx hardware.

Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Jubin John <jubin.john@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/staging/rdma/hfi1/firmware.c

index 4ba524b82edd28fedbdea2389e42d6ab853c0ab0..0b23e3eaf574da331a811c14148ca878ce199a80 100644 (file)
@@ -233,6 +233,8 @@ static const u8 all_pcie_serdes_broadcast = 0xe0;
 
 /* forwards */
 static void dispose_one_firmware(struct firmware_details *fdet);
+static int load_fabric_serdes_firmware(struct hfi1_devdata *dd,
+                                      struct firmware_details *fdet);
 
 /*
  * Read a single 64-bit value from 8051 data memory.
@@ -1092,27 +1094,56 @@ static void turn_off_spicos(struct hfi1_devdata *dd, int flags)
 }
 
 /*
- *  Reset all of the fabric serdes for our HFI.
+ * Reset all of the fabric serdes for this HFI in preparation to take the
+ * link to Polling.
+ *
+ * To do a reset, we need to write to to the serdes registers.  Unfortunately,
+ * the fabric serdes download to the other HFI on the ASIC will have turned
+ * off the firmware validation on this HFI.  This means we can't write to the
+ * registers to reset the serdes.  Work around this by performing a complete
+ * re-download and validation of the fabric serdes firmware.  This, as a
+ * by-product, will reset the serdes.  NOTE: the re-download requires that
+ * the 8051 be in the Offline state.  I.e. not actively trying to use the
+ * serdes.  This routine is called at the point where the link is Offline and
+ * is getting ready to go to Polling.
  */
 void fabric_serdes_reset(struct hfi1_devdata *dd)
 {
-       u8 ra;
-
-       if (dd->icode != ICODE_RTL_SILICON) /* only for RTL */
+       if (!fw_fabric_serdes_load)
                return;
 
-       ra = fabric_serdes_broadcast[dd->hfi1_id];
+       if (is_ax(dd)) {
+               /* A0 serdes do not work with a re-download */
+               u8 ra = fabric_serdes_broadcast[dd->hfi1_id];
+
+               acquire_hw_mutex(dd);
+               set_sbus_fast_mode(dd);
+               /* place SerDes in reset and disable SPICO */
+               sbus_request(dd, ra, 0x07, WRITE_SBUS_RECEIVER, 0x00000011);
+               /* wait 100 refclk cycles @ 156.25MHz => 640ns */
+               udelay(1);
+               /* remove SerDes reset */
+               sbus_request(dd, ra, 0x07, WRITE_SBUS_RECEIVER, 0x00000010);
+               /* turn SPICO enable on */
+               sbus_request(dd, ra, 0x07, WRITE_SBUS_RECEIVER, 0x00000002);
+               clear_sbus_fast_mode(dd);
+               release_hw_mutex(dd);
+               return;
+       }
 
        acquire_hw_mutex(dd);
        set_sbus_fast_mode(dd);
-       /* place SerDes in reset and disable SPICO */
-       sbus_request(dd, ra, 0x07, WRITE_SBUS_RECEIVER, 0x00000011);
-       /* wait 100 refclk cycles @ 156.25MHz => 640ns */
-       udelay(1);
-       /* remove SerDes reset */
-       sbus_request(dd, ra, 0x07, WRITE_SBUS_RECEIVER, 0x00000010);
-       /* turn SPICO enable on */
-       sbus_request(dd, ra, 0x07, WRITE_SBUS_RECEIVER, 0x00000002);
+
+       turn_off_spicos(dd, SPICO_FABRIC);
+       /*
+        * No need for firmware retry - what to download has already been
+        * decided.
+        * No need to pay attention to the load return - the only failure
+        * is a validation failure, which has already been checked by the
+        * initial download.
+        */
+       (void)load_fabric_serdes_firmware(dd, &fw_fabric);
+
        clear_sbus_fast_mode(dd);
        release_hw_mutex(dd);
 }