OCC: FSI and hwmon: Add sequence numbering
authorEddie James <eajames@linux.ibm.com>
Tue, 2 Jul 2019 15:47:42 +0000 (10:47 -0500)
committerJoel Stanley <joel@jms.id.au>
Wed, 3 Jul 2019 01:11:22 +0000 (10:41 +0930)
Sequence numbering of the commands submitted to the OCC is required by
the OCC interface specification. Add sequence numbering and check for
the correct sequence number on the response.

Signed-off-by: Eddie James <eajames@linux.ibm.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Lei YU <mine260309@gmail.com>
Signed-off-by: Joel Stanley <joel@jms.id.au>
drivers/fsi/fsi-occ.c
drivers/hwmon/occ/common.c
drivers/hwmon/occ/common.h

index a2301cea1cbb4fb4aefcb15275d1a6e332c4148e..7da9c81759ac044340084ddda74626468c24dd5a 100644 (file)
@@ -412,6 +412,7 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
                msecs_to_jiffies(OCC_CMD_IN_PRG_WAIT_MS);
        struct occ *occ = dev_get_drvdata(dev);
        struct occ_response *resp = response;
+       u8 seq_no;
        u16 resp_data_length;
        unsigned long start;
        int rc;
@@ -426,6 +427,8 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
 
        mutex_lock(&occ->occ_lock);
 
+       /* Extract the seq_no from the command (first byte) */
+       seq_no = *(const u8 *)request;
        rc = occ_putsram(occ, OCC_SRAM_CMD_ADDR, request, req_len);
        if (rc)
                goto done;
@@ -441,11 +444,17 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len,
                if (rc)
                        goto done;
 
-               if (resp->return_status == OCC_RESP_CMD_IN_PRG) {
+               if (resp->return_status == OCC_RESP_CMD_IN_PRG ||
+                   resp->seq_no != seq_no) {
                        rc = -ETIMEDOUT;
 
-                       if (time_after(jiffies, start + timeout))
-                               break;
+                       if (time_after(jiffies, start + timeout)) {
+                               dev_err(occ->dev, "resp timeout status=%02x "
+                                       "resp seq_no=%d our seq_no=%d\n",
+                                       resp->return_status, resp->seq_no,
+                                       seq_no);
+                               goto done;
+                       }
 
                        set_current_state(TASK_UNINTERRUPTIBLE);
                        schedule_timeout(wait_time);
index 13a6290c8d2548a7db45e19be1e6fb1f771ec5b2..cccf91742c1af2923daffbdb4bd298dcbe3d6c94 100644 (file)
@@ -124,12 +124,12 @@ struct extended_sensor {
 static int occ_poll(struct occ *occ)
 {
        int rc;
-       u16 checksum = occ->poll_cmd_data + 1;
+       u16 checksum = occ->poll_cmd_data + occ->seq_no + 1;
        u8 cmd[8];
        struct occ_poll_response_header *header;
 
        /* big endian */
-       cmd[0] = 0;                     /* sequence number */
+       cmd[0] = occ->seq_no++;         /* sequence number */
        cmd[1] = 0;                     /* cmd type */
        cmd[2] = 0;                     /* data length msb */
        cmd[3] = 1;                     /* data length lsb */
index fc13f3c73c47fb5da042460e23793cbaad925613..67e6968b8978ee720fd0356203746754977dc728 100644 (file)
@@ -95,6 +95,7 @@ struct occ {
        struct occ_sensors sensors;
 
        int powr_sample_time_us;        /* average power sample time */
+       u8 seq_no;
        u8 poll_cmd_data;               /* to perform OCC poll command */
        int (*send_cmd)(struct occ *occ, u8 *cmd);