Skip to content

Commit 679c7a3

Browse files
debox1jwrdegoede
authored andcommitted
platform/x86/intel/sdsi: Handle leaky bucket
To prevent an agent from indefinitely holding the mailbox firmware has implemented a leaky bucket algorithm. Repeated access to the mailbox may now incur a delay of up to 2.1 seconds. Add a retry loop that tries for up to 2.5 seconds to acquire the mailbox. Fixes: 2546c60 ("platform/x86: Add Intel Software Defined Silicon driver") Signed-off-by: David E. Box <david.e.box@linux.intel.com> Link: https://lore.kernel.org/r/20220420155622.1763633-2-david.e.box@linux.intel.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
1 parent 8d75f7b commit 679c7a3

1 file changed

Lines changed: 25 additions & 7 deletions

File tree

  • drivers/platform/x86/intel

drivers/platform/x86/intel/sdsi.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
#define MBOX_TIMEOUT_US 2000
5252
#define MBOX_TIMEOUT_ACQUIRE_US 1000
5353
#define MBOX_POLLING_PERIOD_US 100
54+
#define MBOX_ACQUIRE_NUM_RETRIES 5
55+
#define MBOX_ACQUIRE_RETRY_DELAY_MS 500
5456
#define MBOX_MAX_PACKETS 4
5557

5658
#define MBOX_OWNER_NONE 0x00
@@ -263,7 +265,7 @@ static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info
263265
{
264266
u64 control;
265267
u32 owner;
266-
int ret;
268+
int ret, retries = 0;
267269

268270
lockdep_assert_held(&priv->mb_lock);
269271

@@ -273,13 +275,29 @@ static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info
273275
if (owner != MBOX_OWNER_NONE)
274276
return -EBUSY;
275277

276-
/* Write first qword of payload */
277-
writeq(info->payload[0], priv->mbox_addr);
278+
/*
279+
* If there has been no recent transaction and no one owns the mailbox,
280+
* we should acquire it in under 1ms. However, if we've accessed it
281+
* recently it may take up to 2.1 seconds to acquire it again.
282+
*/
283+
do {
284+
/* Write first qword of payload */
285+
writeq(info->payload[0], priv->mbox_addr);
286+
287+
/* Check for ownership */
288+
ret = readq_poll_timeout(priv->control_addr, control,
289+
FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_INBAND,
290+
MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US);
291+
292+
if (FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_NONE &&
293+
retries++ < MBOX_ACQUIRE_NUM_RETRIES) {
294+
msleep(MBOX_ACQUIRE_RETRY_DELAY_MS);
295+
continue;
296+
}
278297

279-
/* Check for ownership */
280-
ret = readq_poll_timeout(priv->control_addr, control,
281-
FIELD_GET(CTRL_OWNER, control) & MBOX_OWNER_INBAND,
282-
MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US);
298+
/* Either we got it or someone else did. */
299+
break;
300+
} while (true);
283301

284302
return ret;
285303
}

0 commit comments

Comments
 (0)