mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
arm_mpam: resctrl: Allow resctrl to allocate monitors
When resctrl wants to read a domain's 'QOS_L3_OCCUP', it needs to allocate a monitor on the corresponding resource. Monitors are allocated by class instead of component. Add helpers to allocate a CSU monitor. These helper return an out of range value for MBM counters. Allocating a montitor context is expected to block until hardware resources become available. This only makes sense for QOS_L3_OCCUP as unallocated MBM counters are losing data. Tested-by: Gavin Shan <gshan@redhat.com> Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com> Tested-by: Peter Newman <peternewman@google.com> Tested-by: Zeng Heng <zengheng4@huawei.com> Tested-by: Punit Agrawal <punit.agrawal@oss.qualcomm.com> Tested-by: Jesse Chick <jessechick@os.amperecomputing.com> Reviewed-by: Zeng Heng <zengheng4@huawei.com> Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Reviewed-by: Gavin Shan <gshan@redhat.com> Co-developed-by: Ben Horgan <ben.horgan@arm.com> Signed-off-by: Ben Horgan <ben.horgan@arm.com> Signed-off-by: James Morse <james.morse@arm.com>
This commit is contained in:
parent
1458c4f053
commit
2a3c79c615
|
|
@ -29,6 +29,14 @@ struct platform_device;
|
||||||
#define PACKED_FOR_KUNIT
|
#define PACKED_FOR_KUNIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This 'mon' values must not alias an actual monitor, so must be larger than
|
||||||
|
* U16_MAX, but not be confused with an errno value, so smaller than
|
||||||
|
* (u32)-SZ_4K.
|
||||||
|
* USE_PRE_ALLOCATED is used to avoid confusion with an actual monitor.
|
||||||
|
*/
|
||||||
|
#define USE_PRE_ALLOCATED (U16_MAX + 1)
|
||||||
|
|
||||||
static inline bool mpam_is_enabled(void)
|
static inline bool mpam_is_enabled(void)
|
||||||
{
|
{
|
||||||
return static_branch_likely(&mpam_enabled);
|
return static_branch_likely(&mpam_enabled);
|
||||||
|
|
@ -216,7 +224,11 @@ enum mon_filter_options {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mon_cfg {
|
struct mon_cfg {
|
||||||
u16 mon;
|
/*
|
||||||
|
* mon must be large enough to hold out of range values like
|
||||||
|
* USE_PRE_ALLOCATED
|
||||||
|
*/
|
||||||
|
u32 mon;
|
||||||
u8 pmg;
|
u8 pmg;
|
||||||
bool match_pmg;
|
bool match_pmg;
|
||||||
bool csu_exclude_clean;
|
bool csu_exclude_clean;
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@
|
||||||
|
|
||||||
#include "mpam_internal.h"
|
#include "mpam_internal.h"
|
||||||
|
|
||||||
|
DECLARE_WAIT_QUEUE_HEAD(resctrl_mon_ctx_waiters);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The classes we've picked to map to resctrl resources, wrapped
|
* The classes we've picked to map to resctrl resources, wrapped
|
||||||
* in with their resctrl structure.
|
* in with their resctrl structure.
|
||||||
|
|
@ -289,6 +291,71 @@ struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l)
|
||||||
return &mpam_resctrl_controls[l].resctrl_res;
|
return &mpam_resctrl_controls[l].resctrl_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int resctrl_arch_mon_ctx_alloc_no_wait(enum resctrl_event_id evtid)
|
||||||
|
{
|
||||||
|
struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[evtid];
|
||||||
|
|
||||||
|
if (!mon->class)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (evtid) {
|
||||||
|
case QOS_L3_OCCUP_EVENT_ID:
|
||||||
|
/* With CDP, one monitor gets used for both code/data reads */
|
||||||
|
return mpam_alloc_csu_mon(mon->class);
|
||||||
|
case QOS_L3_MBM_LOCAL_EVENT_ID:
|
||||||
|
case QOS_L3_MBM_TOTAL_EVENT_ID:
|
||||||
|
return USE_PRE_ALLOCATED;
|
||||||
|
default:
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r,
|
||||||
|
enum resctrl_event_id evtid)
|
||||||
|
{
|
||||||
|
DEFINE_WAIT(wait);
|
||||||
|
int *ret;
|
||||||
|
|
||||||
|
ret = kmalloc_obj(*ret);
|
||||||
|
if (!ret)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
do {
|
||||||
|
prepare_to_wait(&resctrl_mon_ctx_waiters, &wait,
|
||||||
|
TASK_INTERRUPTIBLE);
|
||||||
|
*ret = resctrl_arch_mon_ctx_alloc_no_wait(evtid);
|
||||||
|
if (*ret == -ENOSPC)
|
||||||
|
schedule();
|
||||||
|
} while (*ret == -ENOSPC && !signal_pending(current));
|
||||||
|
finish_wait(&resctrl_mon_ctx_waiters, &wait);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resctrl_arch_mon_ctx_free_no_wait(enum resctrl_event_id evtid,
|
||||||
|
u32 mon_idx)
|
||||||
|
{
|
||||||
|
struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[evtid];
|
||||||
|
|
||||||
|
if (!mon->class)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (evtid == QOS_L3_OCCUP_EVENT_ID)
|
||||||
|
mpam_free_csu_mon(mon->class, mon_idx);
|
||||||
|
|
||||||
|
wake_up(&resctrl_mon_ctx_waiters);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resctrl_arch_mon_ctx_free(struct rdt_resource *r,
|
||||||
|
enum resctrl_event_id evtid, void *arch_mon_ctx)
|
||||||
|
{
|
||||||
|
u32 mon_idx = *(u32 *)arch_mon_ctx;
|
||||||
|
|
||||||
|
kfree(arch_mon_ctx);
|
||||||
|
|
||||||
|
resctrl_arch_mon_ctx_free_no_wait(evtid, mon_idx);
|
||||||
|
}
|
||||||
|
|
||||||
static bool cache_has_usable_cpor(struct mpam_class *class)
|
static bool cache_has_usable_cpor(struct mpam_class *class)
|
||||||
{
|
{
|
||||||
struct mpam_props *cprops = &class->props;
|
struct mpam_props *cprops = &class->props;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#define __LINUX_ARM_MPAM_H
|
#define __LINUX_ARM_MPAM_H
|
||||||
|
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/resctrl_types.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
struct mpam_msc;
|
struct mpam_msc;
|
||||||
|
|
@ -62,6 +63,10 @@ u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid);
|
||||||
void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid);
|
void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid);
|
||||||
u32 resctrl_arch_system_num_rmid_idx(void);
|
u32 resctrl_arch_system_num_rmid_idx(void);
|
||||||
|
|
||||||
|
struct rdt_resource;
|
||||||
|
void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r, enum resctrl_event_id evtid);
|
||||||
|
void resctrl_arch_mon_ctx_free(struct rdt_resource *r, enum resctrl_event_id evtid, void *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mpam_register_requestor() - Register a requestor with the MPAM driver
|
* mpam_register_requestor() - Register a requestor with the MPAM driver
|
||||||
* @partid_max: The maximum PARTID value the requestor can generate.
|
* @partid_max: The maximum PARTID value the requestor can generate.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user