[PATCH linux dev-4.7 07/12] mtd: spi-nor: aspeed: make locking more explicit

Cédric Le Goater clg at kaod.org
Tue Oct 18 00:20:34 AEDT 2016


On 10/17/2016 07:10 AM, Joel Stanley wrote:
> On Fri, Oct 14, 2016 at 11:07 PM, Cédric Le Goater <clg at kaod.org> wrote:
>> The routine aspeed_smc_stop_user() and aspeed_smc_start_user() hide
>> the fact that they lock an unlock the controller. Change that to make
>> it obvious in the code.
>>
>> Signed-off-by: Cédric Le Goater <clg at kaod.org>
>> ---
>>  drivers/mtd/spi-nor/aspeed-smc.c | 12 ++++++++----
>>  1 file changed, 8 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/aspeed-smc.c
>> index a47eecfdfda2..b22e07d3ef32 100644
>> --- a/drivers/mtd/spi-nor/aspeed-smc.c
>> +++ b/drivers/mtd/spi-nor/aspeed-smc.c
>> @@ -276,8 +276,6 @@ static void aspeed_smc_start_user(struct spi_nor *nor)
>>         struct aspeed_smc_per_chip *chip = nor->priv;
>>         u32 ctl = chip->ctl_val[smc_base];
>>
>> -       mutex_lock(&chip->controller->mutex);
>> -
> 
> This removes all locking from start_user and stop_user. There are some
> accesses and register writes in both of these functions, is that okay?

ah. Indeed, I did half of the job in this patch. Probably when I tried 
to split the changes :/

Currently, the driver only support User mode, in which the parameters of 
an operation on the chip are passed by writing to the address where the 
flash is mapped. So start_user() is always called to start a read or a 
write transaction, if it is to access a flash register or if it is to 
access its data. 

It is completed by calling stop_user(). The flash then goes back to 
a Command mode where operations are driven differently. 

The current flow is not correct from the spi-nor API perspective. I think 
we should be using the prepare() and unprepare() ops instead. I might give 
that a try before mainline. I am pretty sure it will be spotted.

> What is the lock (supposed to be) protecting?

read/write ops which change the controller configuration. The nor has
its own locking so we might not need this lock if we use the prepare() 
and unprepare() ops.
 
> (I note that you effectively add it back in patch 9 where you
> introduce DMA, by putting locks in aspeed_smc_read_user and write_user
> that then calls start_user.)

I made one big patch with all the changes for mainline. We should be 
fine now.

Thanks,

C. 


> 
>>         ctl |= CONTROL_SPI_COMMAND_MODE_USER |
>>                 CONTROL_SPI_CE_STOP_ACTIVE_CONTROL;
>>         writel(ctl, chip->ctl);
>> @@ -296,19 +294,21 @@ static void aspeed_smc_stop_user(struct spi_nor *nor)
>>
>>         writel(ctl2, chip->ctl);        /* stop user CE control */
>>         writel(ctl, chip->ctl);         /* default to fread or read */
>> -
>> -       mutex_unlock(&chip->controller->mutex);
>>  }
>>
>>  static int aspeed_smc_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
>>  {
>>         struct aspeed_smc_per_chip *chip = nor->priv;
>>
>> +       mutex_lock(&chip->controller->mutex);
>> +
>>         aspeed_smc_start_user(nor);
>>         aspeed_smc_to_fifo(chip->base, &opcode, 1);
>>         aspeed_smc_from_fifo(buf, chip->base, len);
>>         aspeed_smc_stop_user(nor);
>>
>> +       mutex_unlock(&chip->controller->mutex);
>> +
>>         return 0;
>>  }
>>
>> @@ -317,11 +317,15 @@ static int aspeed_smc_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
>>  {
>>         struct aspeed_smc_per_chip *chip = nor->priv;
>>
>> +       mutex_lock(&chip->controller->mutex);
>> +
>>         aspeed_smc_start_user(nor);
>>         aspeed_smc_to_fifo(chip->base, &opcode, 1);
>>         aspeed_smc_to_fifo(chip->base, buf, len);
>>         aspeed_smc_stop_user(nor);
>>
>> +       mutex_unlock(&chip->controller->mutex);
>> +
>>         return 0;
>>  }
>>
>> --
>> 2.7.4
>>



More information about the openbmc mailing list