On 07/25/2019 05:00 PM, Boris Brezillon wrote: > External E-Mail > > > On Thu, 25 Jul 2019 13:17:07 +0000 > <Tudor.Ambarus@xxxxxxxxxxxxx> wrote: > >> Hi, Boris, >> >> On 07/25/2019 03:37 PM, Boris Brezillon wrote: >>> External E-Mail >>> >>> >>> On Thu, 25 Jul 2019 11:19:06 +0000 >>> <Tudor.Ambarus@xxxxxxxxxxxxx> wrote: >>> >>>>> + */ >>>>> +static int spi_nor_exec_op(struct spi_nor *nor, struct spi_mem_op *op, >>>>> + u64 *addr, void *buf, size_t len) >>>>> +{ >>>>> + int ret; >>>>> + bool usebouncebuf = false; >>>> >>>> I don't think we need a bounce buffer for regs. What is the maximum size that we >>>> read/write regs, SPI_NOR_MAX_CMD_SIZE(8)? >>>> >>>> In spi-nor.c the maximum length that we pass to nor->read_reg()/write_reg() is >>>> SPI_NOR_MAX_ID_LEN(6). >>>> >>>> I can provide a patch to always use nor->cmd_buf when reading/writing regs so >>>> you respin the series on top of it, if you feel the same. >>>> >>>> With nor->cmd_buf this function will be reduced to the following: >>>> >>>> static int spi_nor_spimem_xfer_reg(struct spi_nor *nor, struct spi_mem_op *op) >>>> { >>>> if (!op || (op->data.nbytes && !nor->cmd_buf)) >>>> return -EINVAL; >>>> >>>> return spi_mem_exec_op(nor->spimem, op); >>>> } >>> >>> Well, I don't think that's a good idea. ->cmd_buf is an array in the >>> middle of the spi_nor struct, which means it won't be aligned on a >>> cache line and you'll have to be extra careful not to touch the spi_nor >>> fields when calling spi_mem_exec_op(). Might work, but I wouldn't take >>> the risk if I were you. >>> >> >> u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE] ____cacheline_aligned; >> >> Does this help? > > I guess you'll also need one on the following field to guarantee that > cmd_buf is covering the whole cache line. TBH, I really prefer the > option of allocating ->cmd_buf. agreed. > >> >>> Another option would be to allocate ->cmd_buf with kmalloc() instead of >>> having it defined as a static array. >>> >>>> >>>> spi_nor_exec_op() always received a NULL addr, let's get rid of it. We won't >>>> need buf anymore and you can retrieve the length from op->data.nbytes. Now that >>>> we trimmed the arguments, I think I would get rid of the >>>> spi_nor_data/nodata_op() wrappers and use spi_nor_spimem_xfer_reg() directly. >>> >>> I think I added the addr param for a good reason (probably to support >>> Octo mode cmds that take an address parameter). This being said, I >>> agree with you, we should just pass everything through the op parameter >>> (including the address if we ever need to add one). >>> >>> >>>>> + >>>>> +/** >>>>> + * spi_nor_spimem_xfer_data() - helper function to read/write data to >>>>> + * flash's memory region >>>>> + * @nor: pointer to 'struct spi_nor' >>>>> + * @op: pointer to 'struct spi_mem_op' template for transfer >>>>> + * @proto: protocol to be used for transfer >>>>> + * >>>>> + * Return: number of bytes transferred on success, -errno otherwise >>>>> + */ >>>>> +static ssize_t spi_nor_spimem_xfer_data(struct spi_nor *nor, >>>>> + struct spi_mem_op *op, >>>>> + enum spi_nor_protocol proto) >>>>> +{ >>>>> + bool usebouncebuf = false; >>>> >>>> declare bool at the end to avoid stack padding. >>> >>> But it breaks the reverse-xmas-tree formatting :-). >>> >>>> >>>>> + void *rdbuf = NULL; >>>>> + const void *buf; >>>> >>>> you can get rid of rdbuf and buf if you pass buf as argument. >>> >>> Hm, passing the buffer to send data from/receive data into is already >>> part of the spi_mem_op definition process (which is done in the caller >>> of this func) so why bother passing an extra arg to the function. >>> Note that you had the exact opposite argument for the >>> spi_nor_spimem_xfer_reg() prototype you suggested above (which I >>> agree with BTW) :P. >> >> In order to avoid if clauses like "if (op->data.dir == SPI_MEM_DATA_IN)". You >> can't use op->data.buf directly, the *out const qualifier can be discarded. > > Not entirely sure why you think this is important to avoid that > test (looks like a micro-optimization to me), but if you really want to > have a non-const buffer, just use the one pointed by op->data.buf.in > (buf is a union so both in and out point to the same thing). Note that > we'd need a comment explaining why this is safe to do that, because > bypassing constness constraints is usually a bad thing. No need for a buf argument, I missed that the const qualifier will be discarded when passing the pointer. We'll keep the function as it is, with the amend that the "enum spi_nor_protocol proto" will be removed from the arguments. Thanks for jumping in, ta ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/