/*
  * Microchip PolarFire SoC (MPFS) system controller/mailbox controller driver
  *
- * Copyright (c) 2020 Microchip Corporation. All rights reserved.
+ * Copyright (c) 2020-2022 Microchip Corporation. All rights reserved.
  *
  * Author: Conor Dooley <conor.dooley@microchip.com>
  *
 #define SCB_STATUS_NOTIFY_MASK BIT(SCB_STATUS_NOTIFY)
 
 #define SCB_STATUS_POS (16)
-#define SCB_STATUS_MASK GENMASK_ULL(SCB_STATUS_POS + SCB_MASK_WIDTH, SCB_STATUS_POS)
+#define SCB_STATUS_MASK GENMASK(SCB_STATUS_POS + SCB_MASK_WIDTH - 1, SCB_STATUS_POS)
 
 struct mpfs_mbox {
        struct mbox_controller controller;
        struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
        struct mpfs_mss_response *response = mbox->response;
        u16 num_words = ALIGN((response->resp_size), (4)) / 4U;
-       u32 i;
+       u32 i, status;
 
        if (!response->resp_msg) {
                dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM);
                return;
        }
 
+       /*
+        * The status is stored in bits 31:16 of the SERVICES_SR register.
+        * It is only valid when BUSY == 0.
+        * We should *never* get an interrupt while the controller is
+        * still in the busy state. If we do, something has gone badly
+        * wrong & the content of the mailbox would not be valid.
+        */
+       if (mpfs_mbox_busy(mbox)) {
+               dev_err(mbox->dev, "got an interrupt but system controller is busy\n");
+               response->resp_status = 0xDEAD;
+               return;
+       }
+
+       status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
+
+       /*
+        * If the status of the individual servers is non-zero, the service has
+        * failed. The contents of the mailbox at this point are not be valid,
+        * so don't bother reading them. Set the status so that the driver
+        * implementing the service can handle the result.
+        */
+       response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS;
+       if (response->resp_status)
+               return;
+
        if (!mpfs_mbox_busy(mbox)) {
                for (i = 0; i < num_words; i++) {
                        response->resp_msg[i] =