Skip to content

Commit ab47d0b

Browse files
ConchuODJassiBrar
authored andcommitted
mailbox: mpfs: read the system controller's status
Some services explicitly return an error code in their response, but others rely on the system controller to set a status in its status register. The meaning of the bits varies based on what service is requested, so pass it back up to the driver that requested the service in the first place. The field in the message struct already existed, but was unused until now. If the system controller is busy, in which case we should never actually be in the interrupt handler, or if the service fails the mailbox itself should not be read. Callers should check the status before operating on the response. There's an existing, but unused, #define for the mailbox mask - but it was incorrect. It was doing a GENMASK_ULL(32, 16) which should've just been a GENMASK(31, 16), so fix that up and start using it. Fixes: 83d7b15 ("mbox: add polarfire soc system controller mailbox") Signed-off-by: Conor Dooley <[email protected]> Reviewed-by: Palmer Dabbelt <[email protected]> Signed-off-by: Jassi Brar <[email protected]>
1 parent 926d621 commit ab47d0b

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

drivers/mailbox/mailbox-mpfs.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
/*
33
* Microchip PolarFire SoC (MPFS) system controller/mailbox controller driver
44
*
5-
* Copyright (c) 2020 Microchip Corporation. All rights reserved.
5+
* Copyright (c) 2020-2022 Microchip Corporation. All rights reserved.
66
*
77
* Author: Conor Dooley <[email protected]>
88
*
@@ -56,7 +56,7 @@
5656
#define SCB_STATUS_NOTIFY_MASK BIT(SCB_STATUS_NOTIFY)
5757

5858
#define SCB_STATUS_POS (16)
59-
#define SCB_STATUS_MASK GENMASK_ULL(SCB_STATUS_POS + SCB_MASK_WIDTH, SCB_STATUS_POS)
59+
#define SCB_STATUS_MASK GENMASK(SCB_STATUS_POS + SCB_MASK_WIDTH - 1, SCB_STATUS_POS)
6060

6161
struct mpfs_mbox {
6262
struct mbox_controller controller;
@@ -130,13 +130,38 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
130130
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
131131
struct mpfs_mss_response *response = mbox->response;
132132
u16 num_words = ALIGN((response->resp_size), (4)) / 4U;
133-
u32 i;
133+
u32 i, status;
134134

135135
if (!response->resp_msg) {
136136
dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM);
137137
return;
138138
}
139139

140+
/*
141+
* The status is stored in bits 31:16 of the SERVICES_SR register.
142+
* It is only valid when BUSY == 0.
143+
* We should *never* get an interrupt while the controller is
144+
* still in the busy state. If we do, something has gone badly
145+
* wrong & the content of the mailbox would not be valid.
146+
*/
147+
if (mpfs_mbox_busy(mbox)) {
148+
dev_err(mbox->dev, "got an interrupt but system controller is busy\n");
149+
response->resp_status = 0xDEAD;
150+
return;
151+
}
152+
153+
status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
154+
155+
/*
156+
* If the status of the individual servers is non-zero, the service has
157+
* failed. The contents of the mailbox at this point are not be valid,
158+
* so don't bother reading them. Set the status so that the driver
159+
* implementing the service can handle the result.
160+
*/
161+
response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS;
162+
if (response->resp_status)
163+
return;
164+
140165
if (!mpfs_mbox_busy(mbox)) {
141166
for (i = 0; i < num_words; i++) {
142167
response->resp_msg[i] =

0 commit comments

Comments
 (0)