[Skiboot-stable] [PATCH 1/3] libflash/ipmi-hiomap: Fix blocks count issue

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Mon Apr 8 15:30:41 AEST 2019


On 04/08/2019 08:38 AM, Andrew Jeffery wrote:
> 
> 
> On Fri, 5 Apr 2019, at 00:03, Vasant Hegde wrote:
>> We convert data size to block count and pass block count to BMC.
>> If data size is not block aligned then we endup sending block count
>> less than actual data. BMC will write partial data to flash memory.
>>
>> Sample log :
>> [  594.388458416,7] HIOMAP: Marked flash dirty at 0x42010 for 8
>> [  594.398756487,7] HIOMAP: Flushed writes
>> [  594.409596439,7] HIOMAP: Marked flash dirty at 0x42018 for 3970
>> [  594.419897507,7] HIOMAP: Flushed writes
>>
>> In this case HIOMAP sent data with block count=0 and hence BMC didn't
>> flush data to flash.
>>
>> Lets fix this issue by adjusting block count before sending it to BMC.
>>
>> Cc: Andrew Jeffery <andrew at aj.id.au>
>> Cc: skiboot-stable at lists.ozlabs.org
>> Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
>> ---
>>   libflash/ipmi-hiomap.c | 16 +++++++++++++---
>>   1 file changed, 13 insertions(+), 3 deletions(-)
>>
>> diff --git a/libflash/ipmi-hiomap.c b/libflash/ipmi-hiomap.c
>> index 56492fa87..da5fa29c9 100644
>> --- a/libflash/ipmi-hiomap.c
>> +++ b/libflash/ipmi-hiomap.c
>> @@ -49,6 +49,16 @@ static inline uint16_t bytes_to_blocks(struct
>> ipmi_hiomap *ctx, uint32_t bytes)
>>   	return bytes >> ctx->block_size_shift;
>>   }
>>   
> 
> I have a bunch of nitty renames below, but I think it improves readability:
> 
>> +static inline uint16_t bytes_to_blocks_align_up(struct ipmi_hiomap
>> *ctx,
>> +						uint32_t pos, uint32_t bytes)
> 
> s/bytes/len
> 
>> +{
>> +	uint32_t size_shift = 1 << ctx->block_size_shift;
> 
> s/size_shift/block_size/
> 
>> +	uint32_t pos_offset = pos & (size_shift - 1);
> 
> Similarly s/pos_offset/delta/
> 
>> +	uint32_t len = ALIGN_UP((bytes + pos_offset), size_shift);
> 
> s/len/aligned/
> 
> Then:
> 
> uint32_t blocks = len >> ctx->block_size_shift;
> 
> We know that we need to fit blocks into a uint16_t as well, but the only
> constraint on ctx->block_size_shift is that it's at least 12. If it is less than
> 16 we probably want to validate that the aligned length we've generated
> fits in a uint16_t, so:
> 
> uint32_t mask = ((1 << 16) - 1);
> 
> assert(!(blocks & ~mask));
> 
> Then:
> 
>   return blocks & mask;
> 
>> +
>> +	return len >> ctx->block_size_shift;
>> +}
> 
> Putting it all together:
> 
> static inline uint16_t bytes_to_blocks_align_up(struct ipmi_hiomap *ctx,
> 						uint32_t pos, uint32_t len)
> {
>      uint32_t block_size = 1 << ctx->block_size_shift;
>      uint32_t delta = pos & (block_size - 1);
>      uint32_t aligned = ALIGN_UP((len + delta), block_size);
>      uint32_t blocks = aligned >> ctx->block_size_shift;
>      uint32_t mask = ((1 << 16) - 1);
> 
>      assert(!(blocks & ~mask));
> 
>      return blocks & mask;
> }
> 
> Thoughts? Note that I haven't tested this suggestion :)

Looks good. It should work fine. Let me test it.

-Vasant



More information about the Skiboot-stable mailing list