Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: stratix10-rsu: extend RSU driver to get DCMF status

Extend RSU driver to get DCMF status.

The status of each DCMF is reported. The currently used DCMF is used as
reference, while the other three are compared against it to determine if
they are corrupted.

DCMF = Decision Configuration Management Firmware.
RSU = Remote System Update

Signed-off-by: Radu Bacrau <radu.bacrau@intel.com>
Signed-off-by: Kah Jing Lee <kah.jing.lee@intel.com>
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
Link: https://lore.kernel.org/r/20220711223140.2307945-4-dinguyen@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Kah Jing Lee and committed by
Greg Kroah-Hartman
4a6c8c56 4a4709d4

+124 -5
+124 -5
drivers/firmware/stratix10-rsu.c
··· 24 24 #define RSU_DCMF1_MASK GENMASK_ULL(63, 32) 25 25 #define RSU_DCMF2_MASK GENMASK_ULL(31, 0) 26 26 #define RSU_DCMF3_MASK GENMASK_ULL(63, 32) 27 + #define RSU_DCMF0_STATUS_MASK GENMASK_ULL(15, 0) 28 + #define RSU_DCMF1_STATUS_MASK GENMASK_ULL(31, 16) 29 + #define RSU_DCMF2_STATUS_MASK GENMASK_ULL(47, 32) 30 + #define RSU_DCMF3_STATUS_MASK GENMASK_ULL(63, 48) 27 31 28 32 #define RSU_TIMEOUT (msecs_to_jiffies(SVC_RSU_REQUEST_TIMEOUT_MS)) 29 33 30 34 #define INVALID_RETRY_COUNTER 0xFF 31 35 #define INVALID_DCMF_VERSION 0xFF 32 - 36 + #define INVALID_DCMF_STATUS 0xFFFFFFFF 33 37 34 38 typedef void (*rsu_callback)(struct stratix10_svc_client *client, 35 39 struct stratix10_svc_cb_data *data); ··· 53 49 * @dcmf_version.dcmf1: Quartus dcmf1 version 54 50 * @dcmf_version.dcmf2: Quartus dcmf2 version 55 51 * @dcmf_version.dcmf3: Quartus dcmf3 version 52 + * @dcmf_status.dcmf0: dcmf0 status 53 + * @dcmf_status.dcmf1: dcmf1 status 54 + * @dcmf_status.dcmf2: dcmf2 status 55 + * @dcmf_status.dcmf3: dcmf3 status 56 56 * @retry_counter: the current image's retry counter 57 57 * @max_retry: the preset max retry value 58 58 */ ··· 80 72 unsigned int dcmf2; 81 73 unsigned int dcmf3; 82 74 } dcmf_version; 75 + 76 + struct { 77 + unsigned int dcmf0; 78 + unsigned int dcmf1; 79 + unsigned int dcmf2; 80 + unsigned int dcmf3; 81 + } dcmf_status; 83 82 84 83 unsigned int retry_counter; 85 84 unsigned int max_retry; ··· 144 129 struct stratix10_rsu_priv *priv = client->priv; 145 130 146 131 if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) 147 - dev_warn(client->dev, "FW doesn't support notify\n"); 132 + dev_warn(client->dev, "Secure FW doesn't support notify\n"); 148 133 else if (data->status == BIT(SVC_STATUS_ERROR)) 149 134 dev_err(client->dev, "Failure, returned status is %lu\n", 150 135 BIT(data->status)); ··· 171 156 if (data->status == BIT(SVC_STATUS_OK)) 172 157 priv->retry_counter = *counter; 173 158 else if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) 174 - dev_warn(client->dev, "FW doesn't support retry\n"); 159 + dev_warn(client->dev, "Secure FW doesn't support retry\n"); 175 160 else 176 161 dev_err(client->dev, "Failed to get retry counter %lu\n", 177 162 BIT(data->status)); ··· 196 181 if (data->status == BIT(SVC_STATUS_OK)) 197 182 priv->max_retry = *max_retry; 198 183 else if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) 199 - dev_warn(client->dev, "FW doesn't support max retry\n"); 184 + dev_warn(client->dev, "Secure FW doesn't support max retry\n"); 200 185 else 201 186 dev_err(client->dev, "Failed to get max retry %lu\n", 202 187 BIT(data->status)); ··· 226 211 priv->dcmf_version.dcmf3 = FIELD_GET(RSU_DCMF3_MASK, *value2); 227 212 } else 228 213 dev_err(client->dev, "failed to get DCMF version\n"); 214 + 215 + complete(&priv->completion); 216 + } 217 + 218 + /** 219 + * rsu_dcmf_status_callback() - Callback from Intel service layer for getting 220 + * the DCMF status 221 + * @client: pointer to client 222 + * @data: pointer to callback data structure 223 + * 224 + * Callback from Intel service layer for DCMF status 225 + */ 226 + static void rsu_dcmf_status_callback(struct stratix10_svc_client *client, 227 + struct stratix10_svc_cb_data *data) 228 + { 229 + struct stratix10_rsu_priv *priv = client->priv; 230 + unsigned long long *value = (unsigned long long *)data->kaddr1; 231 + 232 + if (data->status == BIT(SVC_STATUS_OK)) { 233 + priv->dcmf_status.dcmf0 = FIELD_GET(RSU_DCMF0_STATUS_MASK, 234 + *value); 235 + priv->dcmf_status.dcmf1 = FIELD_GET(RSU_DCMF1_STATUS_MASK, 236 + *value); 237 + priv->dcmf_status.dcmf2 = FIELD_GET(RSU_DCMF2_STATUS_MASK, 238 + *value); 239 + priv->dcmf_status.dcmf3 = FIELD_GET(RSU_DCMF3_STATUS_MASK, 240 + *value); 241 + } else 242 + dev_err(client->dev, "failed to get DCMF status\n"); 229 243 230 244 complete(&priv->completion); 231 245 } ··· 405 361 if (!priv) 406 362 return -ENODEV; 407 363 408 - return sprintf(buf, "0x%08x\n", priv->max_retry); 364 + return scnprintf(buf, sizeof(priv->max_retry), 365 + "0x%08x\n", priv->max_retry); 409 366 } 410 367 411 368 static ssize_t dcmf0_show(struct device *dev, ··· 453 408 return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf3); 454 409 } 455 410 411 + static ssize_t dcmf0_status_show(struct device *dev, 412 + struct device_attribute *attr, char *buf) 413 + { 414 + struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 415 + 416 + if (!priv) 417 + return -ENODEV; 418 + 419 + if (priv->dcmf_status.dcmf0 == INVALID_DCMF_STATUS) 420 + return -EIO; 421 + 422 + return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf0); 423 + } 424 + 425 + static ssize_t dcmf1_status_show(struct device *dev, 426 + struct device_attribute *attr, char *buf) 427 + { 428 + struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 429 + 430 + if (!priv) 431 + return -ENODEV; 432 + 433 + if (priv->dcmf_status.dcmf1 == INVALID_DCMF_STATUS) 434 + return -EIO; 435 + 436 + return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf1); 437 + } 438 + 439 + static ssize_t dcmf2_status_show(struct device *dev, 440 + struct device_attribute *attr, char *buf) 441 + { 442 + struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 443 + 444 + if (!priv) 445 + return -ENODEV; 446 + 447 + if (priv->dcmf_status.dcmf2 == INVALID_DCMF_STATUS) 448 + return -EIO; 449 + 450 + return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf2); 451 + } 452 + 453 + static ssize_t dcmf3_status_show(struct device *dev, 454 + struct device_attribute *attr, char *buf) 455 + { 456 + struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 457 + 458 + if (!priv) 459 + return -ENODEV; 460 + 461 + if (priv->dcmf_status.dcmf3 == INVALID_DCMF_STATUS) 462 + return -EIO; 463 + 464 + return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf3); 465 + } 456 466 static ssize_t reboot_image_store(struct device *dev, 457 467 struct device_attribute *attr, 458 468 const char *buf, size_t count) ··· 584 484 static DEVICE_ATTR_RO(dcmf1); 585 485 static DEVICE_ATTR_RO(dcmf2); 586 486 static DEVICE_ATTR_RO(dcmf3); 487 + static DEVICE_ATTR_RO(dcmf0_status); 488 + static DEVICE_ATTR_RO(dcmf1_status); 489 + static DEVICE_ATTR_RO(dcmf2_status); 490 + static DEVICE_ATTR_RO(dcmf3_status); 587 491 static DEVICE_ATTR_WO(reboot_image); 588 492 static DEVICE_ATTR_WO(notify); 589 493 ··· 604 500 &dev_attr_dcmf1.attr, 605 501 &dev_attr_dcmf2.attr, 606 502 &dev_attr_dcmf3.attr, 503 + &dev_attr_dcmf0_status.attr, 504 + &dev_attr_dcmf1_status.attr, 505 + &dev_attr_dcmf2_status.attr, 506 + &dev_attr_dcmf3_status.attr, 607 507 &dev_attr_reboot_image.attr, 608 508 &dev_attr_notify.attr, 609 509 NULL ··· 640 532 priv->dcmf_version.dcmf2 = INVALID_DCMF_VERSION; 641 533 priv->dcmf_version.dcmf3 = INVALID_DCMF_VERSION; 642 534 priv->max_retry = INVALID_RETRY_COUNTER; 535 + priv->dcmf_status.dcmf0 = INVALID_DCMF_STATUS; 536 + priv->dcmf_status.dcmf1 = INVALID_DCMF_STATUS; 537 + priv->dcmf_status.dcmf2 = INVALID_DCMF_STATUS; 538 + priv->dcmf_status.dcmf3 = INVALID_DCMF_STATUS; 643 539 644 540 mutex_init(&priv->lock); 645 541 priv->chan = stratix10_svc_request_channel_byname(&priv->client, ··· 670 558 0, rsu_dcmf_version_callback); 671 559 if (ret) { 672 560 dev_err(dev, "Error, getting DCMF version %i\n", ret); 561 + stratix10_svc_free_channel(priv->chan); 562 + } 563 + 564 + ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS, 565 + 0, rsu_dcmf_status_callback); 566 + if (ret) { 567 + dev_err(dev, "Error, getting DCMF status %i\n", ret); 673 568 stratix10_svc_free_channel(priv->chan); 674 569 } 675 570