lkml.org 
[lkml]   [2022]   [Aug]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH v2] i2c: designware: Introduce semaphore reservation timer to AMDPSP driver
Date
In order to optimize performance, limit amount of back and forth
transactions between x86 and PSP. This is done by introduction of
semaphore reservation period - that is window in which x86 isn't
releasing the bus immediately after each I2C transaction.

In order to protect PSP from being starved while waiting for
arbitration, after a programmed time bus is automatically released by a
deferred function.

Signed-off-by: Jan Dabros <jsd@semihalf.com>
---
drivers/i2c/busses/i2c-designware-amdpsp.c | 68 +++++++++++++++++-----
1 file changed, 53 insertions(+), 15 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-amdpsp.c b/drivers/i2c/busses/i2c-designware-amdpsp.c
index b624356c945f..b9bdc7db89df 100644
--- a/drivers/i2c/busses/i2c-designware-amdpsp.c
+++ b/drivers/i2c/busses/i2c-designware-amdpsp.c
@@ -6,6 +6,7 @@
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/psp-sev.h>
#include <linux/types.h>
+#include <linux/workqueue.h>

#include <asm/msr.h>

@@ -15,6 +16,8 @@
#define PSP_MBOX_OFFSET 0x10570
#define PSP_CMD_TIMEOUT_US (500 * USEC_PER_MSEC)

+#define PSP_I2C_RESERVATION_TIME_MS 100
+
#define PSP_I2C_REQ_BUS_CMD 0x64
#define PSP_I2C_REQ_RETRY_CNT 400
#define PSP_I2C_REQ_RETRY_DELAY_US (25 * USEC_PER_MSEC)
@@ -240,6 +243,42 @@ static int psp_send_i2c_req(enum psp_i2c_req_type i2c_req_type)
return ret;
}

+static void release_bus(void)
+{
+ int status;
+
+ if (!psp_i2c_sem_acquired)
+ return;
+
+ status = psp_send_i2c_req(PSP_I2C_REQ_RELEASE);
+ if (status)
+ return;
+
+ dev_dbg(psp_i2c_dev, "PSP semaphore held for %ums\n",
+ jiffies_to_msecs(jiffies - psp_i2c_sem_acquired));
+
+ psp_i2c_sem_acquired = 0;
+}
+
+static void psp_release_i2c_bus_deferred(struct work_struct *work)
+{
+
+ mutex_lock(&psp_i2c_access_mutex);
+
+ /*
+ * If there is any pending transaction, cannot release the bus here.
+ * psp_release_i2c_bus will take care of this later.
+ */
+ if (psp_i2c_access_count)
+ goto cleanup;
+
+ release_bus();
+
+cleanup:
+ mutex_unlock(&psp_i2c_access_mutex);
+}
+static DECLARE_DELAYED_WORK(release_queue, psp_release_i2c_bus_deferred);
+
static int psp_acquire_i2c_bus(void)
{
int status;
@@ -250,21 +289,23 @@ static int psp_acquire_i2c_bus(void)
if (psp_i2c_mbox_fail)
goto cleanup;

+ psp_i2c_access_count++;
+
/*
- * Simply increment usage counter and return if PSP semaphore was
- * already taken by kernel.
+ * No need to request bus arbitration once we are inside semaphore
+ * reservation period.
*/
- if (psp_i2c_access_count) {
- psp_i2c_access_count++;
+ if (psp_i2c_sem_acquired)
goto cleanup;
- }

status = psp_send_i2c_req(PSP_I2C_REQ_ACQUIRE);
if (status)
goto cleanup;

psp_i2c_sem_acquired = jiffies;
- psp_i2c_access_count++;
+
+ schedule_delayed_work(&release_queue,
+ msecs_to_jiffies(PSP_I2C_RESERVATION_TIME_MS));

/*
* In case of errors with PSP arbitrator psp_i2c_mbox_fail variable is
@@ -279,8 +320,6 @@ static int psp_acquire_i2c_bus(void)

static void psp_release_i2c_bus(void)
{
- int status;
-
mutex_lock(&psp_i2c_access_mutex);

/* Return early if mailbox was malfunctional */
@@ -295,13 +334,12 @@ static void psp_release_i2c_bus(void)
if (psp_i2c_access_count)
goto cleanup;

- /* Send a release command to PSP */
- status = psp_send_i2c_req(PSP_I2C_REQ_RELEASE);
- if (status)
- goto cleanup;
-
- dev_dbg(psp_i2c_dev, "PSP semaphore held for %ums\n",
- jiffies_to_msecs(jiffies - psp_i2c_sem_acquired));
+ /*
+ * Send a release command to PSP if the semaphore reservation timeout
+ * elapsed but x86 still owns the controller.
+ */
+ if (!delayed_work_pending(&release_queue))
+ release_bus();

cleanup:
mutex_unlock(&psp_i2c_access_mutex);
--
2.37.1.595.g718a3a8f04-goog
\
 
 \ /
  Last update: 2022-08-12 09:18    [W:0.095 / U:0.064 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site