staging/rdma/hfi1: use one-shot LCB write
authorDean Luick <dean.luick@intel.com>
Sat, 7 Nov 2015 01:07:04 +0000 (20:07 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Nov 2015 04:02:47 +0000 (20:02 -0800)
Use the one-shot LCB write implemented in the 8051 firmware.
This speeds up 8051 LCB writes by 2x.  Use old method for older
firmwares.

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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/rdma/hfi1/chip.c
drivers/staging/rdma/hfi1/chip.h

index e842aee00535cb62ae14d1cc61944bfd62dbdfb5..d858f36042b5aa663655aba9881d4b068ea46207 100644 (file)
@@ -4774,13 +4774,25 @@ int read_lcb_csr(struct hfi1_devdata *dd, u32 addr, u64 *data)
  */
 static int write_lcb_via_8051(struct hfi1_devdata *dd, u32 addr, u64 data)
 {
+       u32 regno;
+       int ret;
 
-       if (acquire_lcb_access(dd, 0) == 0) {
-               write_csr(dd, addr, data);
-               release_lcb_access(dd, 0);
-               return 0;
+       if (dd->icode == ICODE_FUNCTIONAL_SIMULATOR ||
+           (dd->dc8051_ver < dc8051_ver(0, 20))) {
+               if (acquire_lcb_access(dd, 0) == 0) {
+                       write_csr(dd, addr, data);
+                       release_lcb_access(dd, 0);
+                       return 0;
+               }
+               return -EBUSY;
        }
-       return -EBUSY;
+
+       /* register is an index of LCB registers: (offset - base) / 8 */
+       regno = (addr - DC_LCB_CFG_RUN) >> 3;
+       ret = do_8051_command(dd, HCMD_WRITE_LCB_CSR, regno, &data);
+       if (ret != HCMD_SUCCESS)
+               return -EBUSY;
+       return 0;
 }
 
 /*
@@ -4861,6 +4873,26 @@ static int do_8051_command(
         * waiting for a command.
         */
 
+       /*
+        * When writing a LCB CSR, out_data contains the full value to
+        * to be written, while in_data contains the relative LCB
+        * address in 7:0.  Do the work here, rather than the caller,
+        * of distrubting the write data to where it needs to go:
+        *
+        * Write data
+        *   39:00 -> in_data[47:8]
+        *   47:40 -> DC8051_CFG_EXT_DEV_0.RETURN_CODE
+        *   63:48 -> DC8051_CFG_EXT_DEV_0.RSP_DATA
+        */
+       if (type == HCMD_WRITE_LCB_CSR) {
+               in_data |= ((*out_data) & 0xffffffffffull) << 8;
+               reg = ((((*out_data) >> 40) & 0xff) <<
+                               DC_DC8051_CFG_EXT_DEV_0_RETURN_CODE_SHIFT)
+                     | ((((*out_data) >> 48) & 0xffff) <<
+                               DC_DC8051_CFG_EXT_DEV_0_RSP_DATA_SHIFT);
+               write_csr(dd, DC_DC8051_CFG_EXT_DEV_0, reg);
+       }
+
        /*
         * Do two writes: the first to stabilize the type and req_data, the
         * second to activate.
index ebf9041a1c5eaceefe1e7c6f2b015b6d62ba6c32..d74aed8ccc18db7d380d38949fbdc5093880d9c1 100644 (file)
 #define HCMD_MISC                 0x05
 #define HCMD_READ_LCB_IDLE_MSG 0x06
 #define HCMD_READ_LCB_CSR      0x07
+#define HCMD_WRITE_LCB_CSR     0x08
 #define HCMD_INTERFACE_TEST       0xff
 
 /* DC_DC8051_CFG_HOST_CMD_1.RETURN_CODE - 8051 host command return */