soc: qcom: llcc: Introduce APIs to support staling mode

Staling mode (Capacity-based or notification-based) is a new feature
that allows for clients to influence cache replacement for their
sub-cache in real time.

Introducing two new APIs:

- llcc_configure_staling_mode() allows for clients to configure the
  staling mode and specify mode-specific parameters such as the staling
  distance for the notification-based mode.

- llcc_notif_staling_inc_counter() increments the frame staling counter
  that ultimately marks previously cached memory at a user-configurable
  frame distance for eviction.

Change-Id: Ied032cd0bead377e294b568a73a713e61159ac2c
Signed-off-by: Guru Das Srinagesh <quic_gurus@quicinc.com>
This commit is contained in:
Guru Das Srinagesh 2022-10-10 18:28:37 -07:00
parent 8c05b73745
commit 2e4da2653a
2 changed files with 178 additions and 1 deletions

View File

@ -47,6 +47,14 @@
#define LLCC_TRP_ACT_CTRLn(n) (n * SZ_4K)
#define LLCC_TRP_ACT_CLEARn(n) (8 + n * SZ_4K)
#define LLCC_TRP_STATUSn(n) (4 + n * SZ_4K)
#define LLCC_TRP_STAL_ATTR0_CFGn(n) (0xC + SZ_4K * n)
#define STALING_TRIGGER_MASK 0x1
#define LLCC_TRP_STAL_ATTR1_CFGn(n) (0x10 + SZ_4K * n)
#define STALING_ENABLE_MASK 0x1
#define STALING_NUM_FRAMES_MASK GENMASK(6, 4)
#define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n)
#define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n)
#define LLCC_TRP_ATTR2_CFGn(n) (0x21100 + SZ_4 * n)
@ -678,6 +686,120 @@ size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
}
EXPORT_SYMBOL_GPL(llcc_get_slice_size);
static int llcc_staling_conf_capacity(u32 sid, struct llcc_staling_mode_params *p)
{
u32 notif_staling_reg;
notif_staling_reg = LLCC_TRP_STAL_ATTR1_CFGn(sid);
return regmap_update_bits(drv_data->bcast_regmap, notif_staling_reg,
STALING_ENABLE_MASK,
LLCC_STALING_MODE_CAPACITY);
}
static int llcc_staling_conf_notify(u32 sid, struct llcc_staling_mode_params *p)
{
u32 notif_staling_reg, staling_distance;
int ret;
if (p->notify_params.op != LLCC_NOTIFY_STALING_WRITEBACK)
return -EINVAL;
notif_staling_reg = LLCC_TRP_STAL_ATTR1_CFGn(sid);
ret = regmap_update_bits(drv_data->bcast_regmap, notif_staling_reg,
STALING_ENABLE_MASK,
LLCC_STALING_MODE_NOTIFY);
if (ret)
return ret;
staling_distance = p->notify_params.staling_distance;
return regmap_update_bits(drv_data->bcast_regmap, notif_staling_reg,
STALING_NUM_FRAMES_MASK, staling_distance);
}
static int (*staling_mode_ops[LLCC_STALING_MODE_MAX])(u32, struct llcc_staling_mode_params *) = {
[LLCC_STALING_MODE_CAPACITY] = llcc_staling_conf_capacity,
[LLCC_STALING_MODE_NOTIFY] = llcc_staling_conf_notify,
};
/**
* llcc_configure_staling_mode - Configure cache staling mode by setting the
* staling_mode and corresponding
* mode-specific params
*
* @desc: Pointer to llcc slice descriptor
* @p: Staling mode-specific params
*
* Returns: zero on success or negative errno.
*/
int llcc_configure_staling_mode(struct llcc_slice_desc *desc,
struct llcc_staling_mode_params *p)
{
u32 sid;
enum llcc_staling_mode m;
if (IS_ERR(drv_data))
return PTR_ERR(drv_data);
if (drv_data->llcc_ver < 50)
return -EOPNOTSUPP;
if (IS_ERR_OR_NULL(desc) || !p)
return -EINVAL;
sid = desc->slice_id;
m = p->staling_mode;
/*
* Look up op corresponding to staling mode and call it
* with the params passed
*/
return (*staling_mode_ops[m])(sid, p);
}
EXPORT_SYMBOL(llcc_configure_staling_mode);
/**
* llcc_notif_staling_inc_counter - Trigger the staling of the sub-cache frame.
*
* @desc: Pointer to llcc slice descriptor
*
* Returns: zero on success or negative errno.
*/
int llcc_notif_staling_inc_counter(struct llcc_slice_desc *desc)
{
u32 sid, stale_trigger_reg, discard;
int ret;
if (IS_ERR(drv_data))
return PTR_ERR(drv_data);
if (drv_data->llcc_ver < 50)
return -EOPNOTSUPP;
if (IS_ERR_OR_NULL(desc))
return -EINVAL;
sid = desc->slice_id;
stale_trigger_reg = LLCC_TRP_STAL_ATTR0_CFGn(sid);
ret = regmap_update_bits(drv_data->bcast_regmap, stale_trigger_reg,
STALING_TRIGGER_MASK, STALING_TRIGGER_MASK);
if (ret)
return ret;
/*
* stale_trigger_reg is a self-clearing reg. Read it anyway to ensure
* that the write went through. We don't care about the value being
* read, so discard it.
*/
return regmap_read(drv_data->bcast_regmap, stale_trigger_reg, &discard);
}
EXPORT_SYMBOL(llcc_notif_staling_inc_counter);
static int qcom_llcc_cfg_program(struct platform_device *pdev)
{
int i;

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/platform_device.h>
@ -124,6 +124,32 @@ struct llcc_drv_data {
struct llcc_slice_desc *desc;
};
/**
* Enum describing the various staling modes available for clients to use.
*/
enum llcc_staling_mode {
LLCC_STALING_MODE_CAPACITY, /* Default option on reset */
LLCC_STALING_MODE_NOTIFY,
LLCC_STALING_MODE_MAX
};
enum llcc_staling_notify_op {
LLCC_NOTIFY_STALING_WRITEBACK,
/* LLCC_NOTIFY_STALING_NO_WRITEBACK, */
LLCC_NOTIFY_STALING_OPS_MAX
};
struct llcc_staling_mode_params {
enum llcc_staling_mode staling_mode;
union {
/* STALING_MODE_CAPACITY needs no params */
struct staling_mode_notify_params {
u8 staling_distance;
enum llcc_staling_notify_op op;
} notify_params;
};
};
#if IS_ENABLED(CONFIG_QCOM_LLCC)
/**
* llcc_slice_getd - get llcc slice descriptor
@ -161,6 +187,26 @@ int llcc_slice_activate(struct llcc_slice_desc *desc);
*/
int llcc_slice_deactivate(struct llcc_slice_desc *desc);
/**
* llcc_configure_staling_mode - Configure cache staling mode by setting the
* staling_mode and corresponding
* mode-specific params
*
* @desc: Pointer to llcc slice descriptor
* @p: Staling mode-specific params
*
* Returns: zero on success or negative errno.
*/
int llcc_configure_staling_mode(struct llcc_slice_desc *desc,
struct llcc_staling_mode_params *p);
/**
* llcc_notif_staling_inc_counter - Trigger the staling of the sub-cache frame.
*
* @desc: Pointer to llcc slice descriptor
*
* Returns: zero on success or negative errno.
*/
int llcc_notif_staling_inc_counter(struct llcc_slice_desc *desc);
#else
static inline struct llcc_slice_desc *llcc_slice_getd(u32 uid)
{
@ -190,6 +236,15 @@ static inline int llcc_slice_deactivate(struct llcc_slice_desc *desc)
{
return -EINVAL;
}
static int llcc_configure_staling_mode(struct llcc_slice_desc *desc,
struct llcc_staling_mode_params *p)
{
return -EINVAL;
}
static inline int llcc_notif_staling_inc_counter(struct llcc_slice_desc *desc)
{
return -EINVAL;
}
#endif
#endif