Skip to content

Commit 37e3430

Browse files
committed
mailbox: mpfs: check the service status in .tx_done()
Services are supposed to generate an interrupt once completed, whether or not they have do so successfully. What appears to be a bug in the system controller means that interrupts are only generated for *successful* services. Currently, the status of a service is only checked in the mpfs_mbox_rx_data() once an interrupt is received. As it turns out, this is not really helpful where the potentially buggy behaviour is present, as we'll only see the status for successes where it is moot anyway. Jassi suggested moving the check to the .tx_done() callback instead. This makes sense, as the busy bit that tx_done() is polling will be lowered on completion, regardless of whether the service passed or failed. That allows us to check the status bits for all services, whether they generate an interrupt or not & pass something more informative than -EBADMSG back to the drivers implementing individual services. Suggested-by: Jassi Brar <jassisinghbrar@gmail.com> Acked-by: Jassi Brar <jaswinder.singh@linaro.org> Tested-by: Valentina Fernandez <valentina.fernandezalanis@microchip.com> Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
1 parent da82f95 commit 37e3430

1 file changed

Lines changed: 16 additions & 16 deletions

File tree

drivers/mailbox/mailbox-mpfs.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,22 @@ static bool mpfs_mbox_busy(struct mpfs_mbox *mbox)
8282
static bool mpfs_mbox_last_tx_done(struct mbox_chan *chan)
8383
{
8484
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
85+
struct mpfs_mss_response *response = mbox->response;
86+
u32 val;
87+
88+
if (mpfs_mbox_busy(mbox))
89+
return false;
90+
91+
/*
92+
* The service status is stored in bits 31:16 of the SERVICES_SR
93+
* register & is only valid when the system controller is not busy.
94+
* Failed services are intended to generated interrupts, but in reality
95+
* this does not happen, so the status must be checked here.
96+
*/
97+
val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
98+
response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS;
8599

86-
return !mpfs_mbox_busy(mbox);
100+
return true;
87101
}
88102

89103
static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
@@ -138,16 +152,14 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
138152
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
139153
struct mpfs_mss_response *response = mbox->response;
140154
u16 num_words = ALIGN((response->resp_size), (4)) / 4U;
141-
u32 i, status;
155+
u32 i;
142156

143157
if (!response->resp_msg) {
144158
dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM);
145159
return;
146160
}
147161

148162
/*
149-
* The status is stored in bits 31:16 of the SERVICES_SR register.
150-
* It is only valid when BUSY == 0.
151163
* We should *never* get an interrupt while the controller is
152164
* still in the busy state. If we do, something has gone badly
153165
* wrong & the content of the mailbox would not be valid.
@@ -158,18 +170,6 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
158170
return;
159171
}
160172

161-
status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
162-
163-
/*
164-
* If the status of the individual servers is non-zero, the service has
165-
* failed. The contents of the mailbox at this point are not be valid,
166-
* so don't bother reading them. Set the status so that the driver
167-
* implementing the service can handle the result.
168-
*/
169-
response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS;
170-
if (response->resp_status)
171-
return;
172-
173173
for (i = 0; i < num_words; i++) {
174174
response->resp_msg[i] =
175175
readl_relaxed(mbox->mbox_base

0 commit comments

Comments
 (0)