Re: [PATCH v5 09/19] iommu/arm-smmu: Consolidate stream map entry state

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

 




On 01/09/16 19:32, Will Deacon wrote:
> On Tue, Aug 23, 2016 at 08:05:20PM +0100, Robin Murphy wrote:
>> In order to consider SMR masking, we really want to be able to validate
>> ID/mask pairs against existing SMR contents to prevent stream match
>> conflicts, which at best would cause transactions to fault unexpectedly,
>> and at worst lead to silent unpredictable behaviour. With our SMMU
>> instance data holding only an allocator bitmap, and the SMR values
>> themselves scattered across master configs hanging off devices which we
>> may have no way of finding, there's essentially no way short of digging
>> everything back out of the hardware. Similarly, the thought of power
>> management ops to support suspend/resume faces the exact same problem.
>>
>> By massaging the software state into a closer shape to the underlying
>> hardware, everything comes together quite nicely; the allocator and the
>> high-level view of the data become a single centralised state which we
>> can easily keep track of, and to which any updates can be validated in
>> full before being synchronised to the hardware itself.
>>
>> Signed-off-by: Robin Murphy <robin.murphy@xxxxxxx>
>> ---
>>  drivers/iommu/arm-smmu.c | 147 +++++++++++++++++++++++++++--------------------
>>  1 file changed, 86 insertions(+), 61 deletions(-)
> 
> [...]
> 
>> +static int arm_smmu_master_alloc_smes(struct arm_smmu_device *smmu,
>> +				      struct arm_smmu_master_cfg *cfg)
>> +{
>> +	struct arm_smmu_smr *smrs = smmu->smrs;
>> +	int i, idx;
>>  
>>  	/* Allocate the SMRs on the SMMU */
>>  	for (i = 0; i < cfg->num_streamids; ++i) {
>> -		int idx = __arm_smmu_alloc_bitmap(smmu->smr_map, 0,
>> -						  smmu->num_mapping_groups);
>> +		if (cfg->smendx[i] >= 0)
>> +			return -EEXIST;
>> +
>> +		/* ...except on stream indexing hardware, of course */
>> +		if (!smrs) {
>> +			cfg->smendx[i] = cfg->streamids[i];
>> +			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;
>>  
>> -		smrs[i] = (struct arm_smmu_smr) {
>> -			.idx	= idx,
>> -			.mask	= 0, /* We don't currently share SMRs */
>> -			.id	= cfg->streamids[i],
>> -		};
>> +		smrs[idx].id = cfg->streamids[i];
>> +		smrs[idx].mask = 0; /* We don't currently share SMRs */
>>  	}
>>  
>> +	if (!smrs)
>> +		return 0;
>> +
>>  	/* It worked! Now, poke the actual hardware */
>> -	for (i = 0; i < cfg->num_streamids; ++i) {
>> -		u32 reg = SMR_VALID | smrs[i].id << SMR_ID_SHIFT |
>> -			  smrs[i].mask << SMR_MASK_SHIFT;
>> -		writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_SMR(smrs[i].idx));
>> -	}
>> +	for (i = 0; i < cfg->num_streamids; ++i)
>> +		arm_smmu_write_smr(smmu, cfg->smendx[i]);
>>  
>> -	cfg->smrs = smrs;
>>  	return 0;
>>  
>>  err_free_smrs:
>> -	while (--i >= 0)
>> -		__arm_smmu_free_bitmap(smmu->smr_map, smrs[i].idx);
>> -	kfree(smrs);
>> +	while (i--) {
>> +		arm_smmu_free_smr(smmu, cfg->smendx[i]);
>> +		cfg->smendx[i] = INVALID_SMENDX;
>> +	}
> 
> Hmm, don't you have an off-by-one here? At least, looking at the final
> code, we branch to out_err from within the for_each_cfg_sme loop, but
> before we've incremented smmu->s2crs[idx].count, so the arm_smmu_free_smr
> will erroneously decrement that.

Given that s2crs only doesn't exist until patch 10, and s2crs->count
doesn't exist until patch 14, I'd have to say pick one of:

a) no

b) ¯\_(ツ)_/¯

Robin.

> 
> Will
> 

--
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