[PATCH v2 23/29] arm_mpam: Add mpam_msmon_read() to read monitor value

James Morse james.morse at arm.com
Thu Oct 9 10:48:49 PDT 2025


Hi Fenghua,

On 25/09/2025 03:30, Fenghua Yu wrote:
> On 9/10/25 13:43, James Morse wrote:
>> Reading a monitor involves configuring what you want to monitor, and
>> reading the value. Components made up of multiple MSC may need values
>> from each MSC. MSCs may take time to configure, returning 'not ready'.
>> The maximum 'not ready' time should have been provided by firmware.
>>
>> Add mpam_msmon_read() to hide all this. If (one of) the MSC returns
>> not ready, then wait the full timeout value before trying again.

>> diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
>> index cf190f896de1..1543c33c5d6a 100644
>> --- a/drivers/resctrl/mpam_devices.c
>> +++ b/drivers/resctrl/mpam_devices.c
>> @@ -898,6 +898,232 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc)

>> +static int _msmon_read(struct mpam_component *comp, struct mon_read *arg)
>> +{
>> +    int err, idx;

> Can err be initialized to some error code e.g. -ENODEV?

Feedback from Jonathan has led to numerous changes here.


>> +    struct mpam_msc *msc;
>> +    struct mpam_vmsc *vmsc;
>> +    struct mpam_msc_ris *ris;
>> +
>> +    idx = srcu_read_lock(&mpam_srcu);
>> +    list_for_each_entry_rcu(vmsc, &comp->vmsc, comp_list) {
>> +        msc = vmsc->msc;
>> +
>> +        list_for_each_entry_rcu(ris, &vmsc->ris, vmsc_list) {
>> +            arg->ris = ris;
>> +
>> +            err = smp_call_function_any(&msc->accessibility,
>> +                            __ris_msmon_read, arg,
>> +                            true);
>> +            if (!err && arg->err)
>> +                err = arg->err;
>> +            if (err)
>> +                break;
>> +        }
>> +        if (err)
>> +            break;
>> +    }
> 
> comp->vmsc or vmsc->ris usually are not empty. But in some condition, they can be empty.

Really? There is no call to create a VMSC - only to create a RIS with a set of ids. If you
provide an ID for a VMSC that doesn't exist yet - it gets created for the RIS to be added to.

There was some defensive programming earlier, (and a comment that said it wasn't
possible). That was some left over debug.


> In that case, uninitialized err value may cause unexpected behavior for the callers.
> 
> So it's better to initialize err to avoid any complexity.

Not complexity - the risk is returning an uninitialised value.

After Jonathan's feedback, and my guess at to what Zheng is seeing, it looks like this:
----------%<----------
static int _msmon_read(struct mpam_component *comp, struct mon_read *arg)
{
	int err,  any_err = 0;
	struct mpam_vmsc *vmsc;

	guard(srcu)(&mpam_srcu);
	list_for_each_entry_srcu(vmsc, &comp->vmsc, comp_list,
				 srcu_read_lock_held(&mpam_srcu)) {
		struct mpam_msc *msc = vmsc->msc;
		struct mpam_msc_ris *ris;

		list_for_each_entry_srcu(ris, &vmsc->ris, vmsc_list,
					 srcu_read_lock_held(&mpam_srcu)) {
			arg->ris = ris;

			err = smp_call_function_any(&msc->accessibility,
						    __ris_msmon_read, arg,
						    true);
			if (!err && arg->err)
				err = arg->err;

			/*
			 * Save one error to be returned to the caller, but
			 * keep reading counters so that get reprogrammed. On
			 * platforms with NRDY this lets us wait once.
			 */
			if (err)
				any_err = err;
		}
	}

	return any_err;
}
----------%<----------


>> +    srcu_read_unlock(&mpam_srcu, idx);
>> +
>> +    return err;
>> +}


Thanks,

James



More information about the linux-arm-kernel mailing list