[U-Boot] [Patch V5 2/4] spi: fsl_qspi: Fix qspi_op_rdid memcpy issue

york sun york.sun at nxp.com
Mon Jan 25 18:01:59 CET 2016


On 01/25/2016 09:01 AM, Scott Wood wrote:
> On 01/25/2016 10:47 AM, york sun wrote:
>> On 01/24/2016 08:09 PM, Yao Yuan wrote:
>>> On 01/25/2016 04:16 AM, York Sun wrote:
>>>> On 01/22/2016 07:43 AM, Scott Wood wrote:
>>>>> On 01/21/2016 09:35 PM, Qianyu Gong wrote:
>>>>>>
>>>>>>> -----Original Message-----
>>>>>>> From: Scott Wood
>>>>>>> Sent: Friday, January 22, 2016 3:30 AM
>>>>>>> To: Qianyu Gong <qianyu.gong at nxp.com>; u-boot at lists.denx.de;
>>>>>>> R58495 at freescale.com
>>>>>>> Cc: Mingkai.Hu at freescale.com; jteki at openedev.com;
>>>>>>> B48286 at freescale.com; Shaohui.Xie at freescale.com;
>>>>>>> Wenbin.Song at freescale.com; Scott Wood <oss at buserror.net>; Gong
>>>>>>> Qianyu <Qianyu.Gong at freescale.com>
>>>>>>> Subject: Re: [Patch V5 2/4] spi: fsl_qspi: Fix qspi_op_rdid memcpy
>>>>>>> issue
>>>>>>>
>>>>>>> On 01/20/2016 09:43 PM, Gong Qianyu wrote:
>>>>>>>> From: Gong Qianyu <Qianyu.Gong at freescale.com>
>>>>>>>>
>>>>>>>> In current driver everytime we memcpy 4 bytes to the dest memory
>>>>>>>> regardless of the remaining length.
>>>>>>>> This patch adds checking the remaining length before memcpy.
>>>>>>>> If the length is shorter than 4 bytes, memcpy the actual length of
>>>>>>>> data to the dest memory.
>>>>>>>>
>>>>>>>> Signed-off-by: Gong Qianyu <Qianyu.Gong at freescale.com>
>>>>>>>> ---
>>>>>>>> V2-V5:
>>>>>>>>  - No change.
>>>>>>>>
>>>>>>>>  drivers/spi/fsl_qspi.c | 5 ++++-
>>>>>>>>  1 file changed, 4 insertions(+), 1 deletion(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index
>>>>>>>> 38e5900..f178857 100644
>>>>>>>> --- a/drivers/spi/fsl_qspi.c
>>>>>>>> +++ b/drivers/spi/fsl_qspi.c
>>>>>>>> @@ -500,7 +500,10 @@ static void qspi_op_rdid(struct fsl_qspi_priv
>>>>>>>> *priv, u32
>>>>>>> *rxbuf, u32 len)
>>>>>>>>  		if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {
>>>>>>>>  			data = qspi_read32(priv->flags, &regs->rbdr[i]);
>>>>>>>>  			data = qspi_endian_xchg(data);
>>>>>>>> -			memcpy(rxbuf, &data, 4);
>>>>>>>> +			if (size < 4)
>>>>>>>> +				memcpy(rxbuf, &data, size);
>>>>>>>> +			else
>>>>>>>> +				memcpy(rxbuf, &data, 4);
>>>>>>>
>>>>>>> memcpy(rxbuf, &data, min(size, 4));
>>>>>>>
>>>>>>>>  			rxbuf++;
>>>>>>>>  			size -= 4;
>>>>>>>>  			i++;
>>>>>>>
>>>>>>> size -= 4 even if size was < 4?
>>>>>>>
>>>>>>> -Scott
>>>>>>
>>>>>> Yes.. The following is complete code:
>>>>>>
>>>>>>         i = 0;
>>>>>>         size = len;
>>>>>>         while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
>>>>>>                 rbsr_reg = qspi_read32(priv->flags, &regs->rbsr);
>>>>>>                 if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {
>>>>>>                         data = qspi_read32(priv->flags, &regs->rbdr[i]);
>>>>>>                         data = qspi_endian_xchg(data);
>>>>>>                         memcpy(rxbuf, &data, min(size, 4));
>>>>>>                         rxbuf++;
>>>>>>                         size -= 4;
>>>>>>                         i++;
>>>>>>                 }
>>>>>>         }
>>>>>
>>>>> I'm not saying it doesn't work (assuming i is signed, which the
>>>>> "complete code" above doesn't show).  I'm saying it looks weird, and
>>>>> it would be better to have a variable that holds min(size, 4) and pass
>>>>> that to both memcpy and the subtraction.
>>>>>
>>>>
>>>> Qianyu,
>>>>
>>>> Previously I said it looked weird for doing this. Please fix.
>>>>
>>>> "size" is declared as "int".
>>>> "len" is declared as u32. That's not "int". If you trace back the functions, you
>>>> may see it came from DIV_ROUND_UP(bitlen, 8) where bitlen is "unsigned int".
>>>> So technically the code is safe. But it is _confusing_. We don't want to confuse
>>>> ourselves when reading the code later. And the fix is easy, isn't it?
>>>>
>>>> York
>>>>
>>>
>>> How about like this?
>>>
>>> diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
>>> index feec3e8..13bba09 100644
>>> --- a/drivers/spi/fsl_qspi.c
>>> +++ b/drivers/spi/fsl_qspi.c
>>> @@ -477,8 +477,8 @@ static void qspi_op_rdbank(struct fsl_qspi_priv *priv, u8 *rxbuf, u32 len)
>>>  static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
>>>  {
>>>         struct fsl_qspi_regs *regs = priv->regs;
>>> -       u32 mcr_reg, rbsr_reg, data;
>>> -       int i, size;
>>> +       u32 mcr_reg, rbsr_reg, data, size;
>>> +       int i;
>>>
>>>         mcr_reg = qspi_read32(priv->flags, &regs->mcr);
>>>         qspi_write32(priv->flags, &regs->mcr,
>>> @@ -495,14 +495,14 @@ static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len)
>>>
>>>         i = 0;
>>>         size = len;
>>> -       while ((RX_BUFFER_SIZE >= size) && (size > 0)) {
>>> +       while ((RX_BUFFER_SIZE >= size) && (size != 0)) {
>>
>> You can keep using "size > 0". It is still correct.
> 
> And more robust.
> 
>>
>>>                 rbsr_reg = qspi_read32(priv->flags, &regs->rbsr);
>>>                 if (rbsr_reg & QSPI_RBSR_RDBFL_MASK) {
>>>                         data = qspi_read32(priv->flags, &regs->rbdr[i]);
>>>                         data = qspi_endian_xchg(data);
>>> -                       memcpy(rxbuf, &data, 4);
>>> +                       memcpy(rxbuf, &data, min(size, 4));
>>> +                       size = (size < 4) ? 0 : ( size - 4);
>>>                         rxbuf++;
>>> -                       size -= 4;
>>>                         i++;
>>>                 }
>>>         }
>>>
>>
>> The rest looks OK to me.
> 
> It's still awkward compared to:
> 
> int chunk;
> 
> ...
> 
> chunk = min(size, 4);
> memcpy(rxbuf, &data, chunk);
> size -= chunk;
> 

Agree.

York




More information about the U-Boot mailing list