Hi, Sergei, Looks good. Just a nit below that I can fix it when applying. Let me know if you're ok with the change. On Monday, January 27, 2020 10:28:05 PM EET Sergei Shtylyov wrote: > EXTERNAL EMAIL: Do not click links or open attachments unless you know the > content is safe > > spi_nor_spimem_xfer_data() being a helper function for the data reads/ > writes contains 3 fragments that depend on the data direction; and I'm > going to add another one to call the SPI dirmap API... > I think this function should be split so that the common fragments are > put into 2 functions, spi_nor_spimem_bounce() and spi_nor_spimem_exec_op() > called from spi_nor_spimem_{read|write}_data(), and the data direction > dependent bits moved back into those read/write functions -- that way we > would be able to avoid *goto*s otherwise needed in the next patch adding > the SPI dirmap support... > > Signed-off-by: Sergei Shtylyov <sergei.shtylyov@xxxxxxxxxxxxxxxxxx> > > --- > Changes in version 4: > - new patch. > > drivers/mtd/spi-nor/spi-nor.c | 91 > +++++++++++++++++++++++------------------- 1 file changed, 51 > insertions(+), 40 deletions(-) > > Index: linux/drivers/mtd/spi-nor/spi-nor.c > =================================================================== > --- linux.orig/drivers/mtd/spi-nor/spi-nor.c > +++ linux/drivers/mtd/spi-nor/spi-nor.c > @@ -246,55 +246,45 @@ struct flash_info { > #define JEDEC_MFR(info) ((info)->id[0]) > > /** > - * spi_nor_spimem_xfer_data() - helper function to read/write data to > - * flash's memory region > + * spi_nor_spimem_bounce() - check if a bounce buffer is needed for the > data + * transfer > * @nor: pointer to 'struct spi_nor' > * @op: pointer to 'struct spi_mem_op' template for transfer > * > - * Return: number of bytes transferred on success, -errno otherwise > + * If we have to use the bounce buffer, the data field in @op will be > updated. + * > + * Return: true if the bounce buffer is needed, false if not > */ > -static ssize_t spi_nor_spimem_xfer_data(struct spi_nor *nor, > - struct spi_mem_op *op) > +static bool spi_nor_spimem_bounce(struct spi_nor *nor, struct spi_mem_op > *op) { > - bool usebouncebuf = false; > - void *rdbuf = NULL; > - const void *buf; > - int ret; > - > - if (op->data.dir == SPI_MEM_DATA_IN) > - buf = op->data.buf.in; > - else > - buf = op->data.buf.out; > - > - if (object_is_on_stack(buf) || !virt_addr_valid(buf)) > - usebouncebuf = true; > - > - if (usebouncebuf) { > + /* op->data.buf.in occupies the same memory as op->data.buf.out */ > + if (object_is_on_stack(op->data.buf.in) || > + !virt_addr_valid(op->data.buf.in)) { > if (op->data.nbytes > nor->bouncebuf_size) > op->data.nbytes = nor->bouncebuf_size; > - > - if (op->data.dir == SPI_MEM_DATA_IN) { > - rdbuf = op->data.buf.in; > - op->data.buf.in = nor->bouncebuf; > - } else { > - op->data.buf.out = nor->bouncebuf; > - memcpy(nor->bouncebuf, buf, > - op->data.nbytes); > - } > + op->data.buf.in = nor->bouncebuf; > + return true; > } > > - ret = spi_mem_adjust_op_size(nor->spimem, op); > - if (ret) > - return ret; > - > - ret = spi_mem_exec_op(nor->spimem, op); > - if (ret) > - return ret; > + return false; > +} > + > +/** > + * spi_nor_spimem_exec_op() - execute a memory operation > + * @nor: pointer to 'struct spi_nor' > + * @op: pointer to 'struct spi_mem_op' template for transfer > + * > + * Return: 0 on success, -error otherwise. > + */ > +static int spi_nor_spimem_exec_op(struct spi_nor *nor, struct spi_mem_op > *op) +{ > + int error; > > - if (usebouncebuf && op->data.dir == SPI_MEM_DATA_IN) > - memcpy(rdbuf, nor->bouncebuf, op->data.nbytes); > + error = spi_mem_adjust_op_size(nor->spimem, op); > + if (error) > + return error; > > - return op->data.nbytes; > + return spi_mem_exec_op(nor->spimem, op); > } > > /** > @@ -315,6 +305,8 @@ static ssize_t spi_nor_spimem_read_data( > SPI_MEM_OP_ADDR(nor->addr_width, from, 1), > SPI_MEM_OP_DUMMY(nor->read_dummy, 1), > SPI_MEM_OP_DATA_IN(len, buf, 1)); > + bool usebouncebuf; > + int error; > > /* get transfer protocols. */ > op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto); > @@ -325,7 +317,16 @@ static ssize_t spi_nor_spimem_read_data( > /* convert the dummy cycles to the number of bytes */ > op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8; > > - return spi_nor_spimem_xfer_data(nor, &op); > + usebouncebuf = spi_nor_spimem_bounce(nor, &op); > + > + error = spi_nor_spimem_exec_op(nor, &op); > + if (error) > + return error; > + > + if (usebouncebuf) > + memcpy(buf, op.data.buf.in, op.data.nbytes); > + > + return op.data.nbytes; > } > > /** > @@ -364,6 +365,8 @@ static ssize_t spi_nor_spimem_write_data > SPI_MEM_OP_ADDR(nor->addr_width, to, 1), > SPI_MEM_OP_NO_DUMMY, > SPI_MEM_OP_DATA_OUT(len, buf, 1)); > + bool usebouncebuf; > + int error; > > op.cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto); > op.addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto); @@ > -372,7 +375,15 @@ static ssize_t spi_nor_spimem_write_data > if (nor->program_opcode == SPINOR_OP_AAI_WP && > nor->sst_write_second) op.addr.nbytes = 0; > > - return spi_nor_spimem_xfer_data(nor, &op); > + usebouncebuf = spi_nor_spimem_bounce(nor, &op); > + if (usebouncebuf) > + memcpy(nor->bouncebuf, buf, op.data.nbytes); How about memcpy(nor->bouncebuf, buf, len); instead? spi_nor_spimem_bounce() does not modify op.data.nbytes. Using len is more straight forward than op.data.bytes because the reader doesn't have to verify if length was updated in spi_nor_spimem_bounce() or not. Cheers, ta ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/