Re: [PATCH v5 14/19] iommu/arm-smmu: Intelligent SMR allocation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 01/09/16 16:17, Lorenzo Pieralisi wrote:
[...]
>> +static int arm_smmu_find_sme(struct arm_smmu_device *smmu, u16 id, u16 mask)
>>  {
>>  	struct arm_smmu_smr *smrs = smmu->smrs;
>> -	int i, idx;
>> +	int i, idx = -ENOSPC;
>>  
>> -	/* Allocate the SMRs on the SMMU */
>> -	for_each_cfg_sme(cfg, i, idx) {
>> -		if (idx >= 0)
>> -			return -EEXIST;
>> +	/* Stream indexing is blissfully easy */
>> +	if (!smrs)
>> +		return id;
>>  
>> -		/* ...except on stream indexing hardware, of course */
>> -		if (!smrs) {
>> -			cfg->smendx[i] = cfg->streamids[i];
>> +	/* Validating SMRs is... less so */
>> +	for (i = 0; i < smmu->num_mapping_groups; ++i) {
>> +		if (!smrs[i].valid) {
>> +			if (idx < 0)
>> +				idx = i;
> 
> This is to stash an "empty" entry index in case none matches, right ?
> Let me say it is not that obvious, that deserves a comment since it
> is hard to follow.

Yes, since we have to iterate through every SMR anyway, this just keeps
a note of the first free entry we see along the way. It _could_ be
simplified slightly further by being made unconditional so that we end
up allocating top-down instead, although that would pessimize the
early-out cases below. I'll certainly comment it, though.

>>  			continue;
>>  		}
>>  
>> -		idx = arm_smmu_alloc_smr(smmu);
>> -		if (idx < 0) {
>> -			dev_err(smmu->dev, "failed to allocate free SMR\n");
>> -			goto err_free_smrs;
>> -		}
>> -		cfg->smendx[i] = idx;
>> +		/* Exact matches are good */
>> +		if (mask == smrs[i].mask && id == smrs[i].id)
>> +			return i;
>>  
>> -		smrs[idx].id = cfg->streamids[i];
>> -		smrs[idx].mask = 0; /* We don't currently share SMRs */
>> +		/* New unmasked IDs matching existing masks we can cope with */
>> +		if (!mask && !((smrs[i].id ^ id) & ~smrs[i].mask))
>> +			return i;
>> +
>> +		/* Overlapping masks are right out */
>> +		if (mask & smrs[i].mask)
>> +			return -EINVAL;
>> +
>> +		/* Distinct masks must match unambiguous ranges */
>> +		if (mask && !((smrs[i].id ^ id) & ~(smrs[i].mask | mask)))
>> +			return -EINVAL;
> 
> And this is to _prevent_ an entry to match the input streamid
> range (masked streamid) because it would create an ambiguous match ?

Indeed; say we have the (ID,mask) pair (0x0100,0x000f) already in an
SMR, then we'd allow (0x0000,0x00f0), since bit 8 still uniquely matches
one or the other, but we'd have to reject (0x0100,0x00f0) as that would
create a conflict for ID 0x0100. In general, unless there are distinct
bits outside both masks then there will always exist at least one ID
capable of causing a conflict.

> Basically here you keep looping because this function is at the
> same time allocating and validating the SMRS (ie you want to make
> sure there are no valid entries that clash with the streamid you
> are currently allocating).
> 
> It is a tad complicated and a bit hard to parse. I wonder if it would
> not be better to split into two SMRS validation and allocation
> functions, I think I fully grasped what you want to achieve but it is
> not that trivial.

Things were actually considerably more complicated until I realised the
neatness of hoisting the allocation (which itself is all of 4 lines
here) up into the same function. A real logical separation of concerns
would involve iterating through the whole array two-and-a-bit times,
first validating against conflicts, then looking to return an existing
entry which already matches, then finally falling back to allocating a
free entry. Even disregarding the efficiency angle, I'm not convinced
that having more code spread about with similar but subtly different
repetition would actually be any easier to follow (unfortunately earlier
implementations of this have been rebased into oblivion so I can't pull
one out to demonstrate). I'll definitely beef up the comments here - on
reflection these are more notes to myself than actual explanations for
others...

Robin.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux