Merge tag '6.6-rc-smb3-client-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6
[sfrench/cifs-2.6.git] / drivers / firmware / stratix10-rsu.c
index ab30747053802030ddec99b5468857093bcd770b..4f7a7abada48a6b5deadd226ed8d60738c20b6cd 100644 (file)
 #define INVALID_RETRY_COUNTER          0xFF
 #define INVALID_DCMF_VERSION           0xFF
 #define INVALID_DCMF_STATUS            0xFFFFFFFF
+#define INVALID_SPT_ADDRESS            0x0
+
+#define RSU_GET_SPT_CMD                        0x5A
+#define RSU_GET_SPT_RESP_LEN           (4 * sizeof(unsigned int))
 
 typedef void (*rsu_callback)(struct stratix10_svc_client *client,
                             struct stratix10_svc_cb_data *data);
@@ -58,6 +62,9 @@ typedef void (*rsu_callback)(struct stratix10_svc_client *client,
  * @dcmf_status.dcmf3: dcmf3 status
  * @retry_counter: the current image's retry counter
  * @max_retry: the preset max retry value
+ * @spt0_address: address of spt0
+ * @spt1_address: address of spt1
+ * @get_spt_response_buf: response from sdm for get_spt command
  */
 struct stratix10_rsu_priv {
        struct stratix10_svc_chan *chan;
@@ -89,6 +96,11 @@ struct stratix10_rsu_priv {
 
        unsigned int retry_counter;
        unsigned int max_retry;
+
+       unsigned long spt0_address;
+       unsigned long spt1_address;
+
+       unsigned int *get_spt_response_buf;
 };
 
 /**
@@ -258,6 +270,36 @@ static void rsu_dcmf_status_callback(struct stratix10_svc_client *client,
        complete(&priv->completion);
 }
 
+static void rsu_get_spt_callback(struct stratix10_svc_client *client,
+                                struct stratix10_svc_cb_data *data)
+{
+       struct stratix10_rsu_priv *priv = client->priv;
+       unsigned long *mbox_err = (unsigned long *)data->kaddr1;
+       unsigned long *resp_len = (unsigned long *)data->kaddr2;
+
+       if (data->status != BIT(SVC_STATUS_OK) || (*mbox_err) ||
+           (*resp_len != RSU_GET_SPT_RESP_LEN))
+               goto error;
+
+       priv->spt0_address = priv->get_spt_response_buf[0];
+       priv->spt0_address <<= 32;
+       priv->spt0_address |= priv->get_spt_response_buf[1];
+
+       priv->spt1_address = priv->get_spt_response_buf[2];
+       priv->spt1_address <<= 32;
+       priv->spt1_address |= priv->get_spt_response_buf[3];
+
+       goto complete;
+
+error:
+       dev_err(client->dev, "failed to get SPTs\n");
+
+complete:
+       stratix10_svc_free_memory(priv->chan, priv->get_spt_response_buf);
+       priv->get_spt_response_buf = NULL;
+       complete(&priv->completion);
+}
+
 /**
  * rsu_send_msg() - send a message to Intel service layer
  * @priv: pointer to rsu private data
@@ -287,6 +329,14 @@ static int rsu_send_msg(struct stratix10_rsu_priv *priv,
        if (arg)
                msg.arg[0] = arg;
 
+       if (command == COMMAND_MBOX_SEND_CMD) {
+               msg.arg[1] = 0;
+               msg.payload = NULL;
+               msg.payload_length = 0;
+               msg.payload_output = priv->get_spt_response_buf;
+               msg.payload_length_output = RSU_GET_SPT_RESP_LEN;
+       }
+
        ret = stratix10_svc_send(priv->chan, &msg);
        if (ret < 0)
                goto status_done;
@@ -571,6 +621,34 @@ static ssize_t notify_store(struct device *dev,
        return count;
 }
 
+static ssize_t spt0_address_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
+
+       if (!priv)
+               return -ENODEV;
+
+       if (priv->spt0_address == INVALID_SPT_ADDRESS)
+               return -EIO;
+
+       return scnprintf(buf, PAGE_SIZE, "0x%08lx\n", priv->spt0_address);
+}
+
+static ssize_t spt1_address_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
+
+       if (!priv)
+               return -ENODEV;
+
+       if (priv->spt1_address == INVALID_SPT_ADDRESS)
+               return -EIO;
+
+       return scnprintf(buf, PAGE_SIZE, "0x%08lx\n", priv->spt1_address);
+}
+
 static DEVICE_ATTR_RO(current_image);
 static DEVICE_ATTR_RO(fail_image);
 static DEVICE_ATTR_RO(state);
@@ -589,6 +667,8 @@ static DEVICE_ATTR_RO(dcmf2_status);
 static DEVICE_ATTR_RO(dcmf3_status);
 static DEVICE_ATTR_WO(reboot_image);
 static DEVICE_ATTR_WO(notify);
+static DEVICE_ATTR_RO(spt0_address);
+static DEVICE_ATTR_RO(spt1_address);
 
 static struct attribute *rsu_attrs[] = {
        &dev_attr_current_image.attr,
@@ -609,6 +689,8 @@ static struct attribute *rsu_attrs[] = {
        &dev_attr_dcmf3_status.attr,
        &dev_attr_reboot_image.attr,
        &dev_attr_notify.attr,
+       &dev_attr_spt0_address.attr,
+       &dev_attr_spt1_address.attr,
        NULL
 };
 
@@ -638,11 +720,13 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
        priv->dcmf_version.dcmf1 = INVALID_DCMF_VERSION;
        priv->dcmf_version.dcmf2 = INVALID_DCMF_VERSION;
        priv->dcmf_version.dcmf3 = INVALID_DCMF_VERSION;
-       priv->max_retry = INVALID_RETRY_COUNTER;
        priv->dcmf_status.dcmf0 = INVALID_DCMF_STATUS;
        priv->dcmf_status.dcmf1 = INVALID_DCMF_STATUS;
        priv->dcmf_status.dcmf2 = INVALID_DCMF_STATUS;
        priv->dcmf_status.dcmf3 = INVALID_DCMF_STATUS;
+       priv->max_retry = INVALID_RETRY_COUNTER;
+       priv->spt0_address = INVALID_SPT_ADDRESS;
+       priv->spt1_address = INVALID_SPT_ADDRESS;
 
        mutex_init(&priv->lock);
        priv->chan = stratix10_svc_request_channel_byname(&priv->client,
@@ -692,6 +776,20 @@ static int stratix10_rsu_probe(struct platform_device *pdev)
                stratix10_svc_free_channel(priv->chan);
        }
 
+       priv->get_spt_response_buf =
+               stratix10_svc_allocate_memory(priv->chan, RSU_GET_SPT_RESP_LEN);
+
+       if (IS_ERR(priv->get_spt_response_buf)) {
+               dev_err(dev, "failed to allocate get spt buffer\n");
+       } else {
+               ret = rsu_send_msg(priv, COMMAND_MBOX_SEND_CMD,
+                                  RSU_GET_SPT_CMD, rsu_get_spt_callback);
+               if (ret) {
+                       dev_err(dev, "Error, getting SPT table %i\n", ret);
+                       stratix10_svc_free_channel(priv->chan);
+               }
+       }
+
        return ret;
 }