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: 2546c60004
("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>
This commit is contained in:
Родитель
8d75f7b4a3
Коммит
679c7a3f15
|
@ -51,6 +51,8 @@
|
|||
#define MBOX_TIMEOUT_US 2000
|
||||
#define MBOX_TIMEOUT_ACQUIRE_US 1000
|
||||
#define MBOX_POLLING_PERIOD_US 100
|
||||
#define MBOX_ACQUIRE_NUM_RETRIES 5
|
||||
#define MBOX_ACQUIRE_RETRY_DELAY_MS 500
|
||||
#define MBOX_MAX_PACKETS 4
|
||||
|
||||
#define MBOX_OWNER_NONE 0x00
|
||||
|
@ -263,7 +265,7 @@ static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info
|
|||
{
|
||||
u64 control;
|
||||
u32 owner;
|
||||
int ret;
|
||||
int ret, retries = 0;
|
||||
|
||||
lockdep_assert_held(&priv->mb_lock);
|
||||
|
||||
|
@ -273,13 +275,29 @@ static int sdsi_mbox_acquire(struct sdsi_priv *priv, struct sdsi_mbox_info *info
|
|||
if (owner != MBOX_OWNER_NONE)
|
||||
return -EBUSY;
|
||||
|
||||
/* Write first qword of payload */
|
||||
writeq(info->payload[0], priv->mbox_addr);
|
||||
/*
|
||||
* If there has been no recent transaction and no one owns the mailbox,
|
||||
* we should acquire it in under 1ms. However, if we've accessed it
|
||||
* recently it may take up to 2.1 seconds to acquire it again.
|
||||
*/
|
||||
do {
|
||||
/* Write first qword of payload */
|
||||
writeq(info->payload[0], priv->mbox_addr);
|
||||
|
||||
/* Check for ownership */
|
||||
ret = readq_poll_timeout(priv->control_addr, control,
|
||||
FIELD_GET(CTRL_OWNER, control) & MBOX_OWNER_INBAND,
|
||||
MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US);
|
||||
/* Check for ownership */
|
||||
ret = readq_poll_timeout(priv->control_addr, control,
|
||||
FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_INBAND,
|
||||
MBOX_POLLING_PERIOD_US, MBOX_TIMEOUT_ACQUIRE_US);
|
||||
|
||||
if (FIELD_GET(CTRL_OWNER, control) == MBOX_OWNER_NONE &&
|
||||
retries++ < MBOX_ACQUIRE_NUM_RETRIES) {
|
||||
msleep(MBOX_ACQUIRE_RETRY_DELAY_MS);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Either we got it or someone else did. */
|
||||
break;
|
||||
} while (true);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче