[PATCH] eeprom: at25: Convert the driver to the spi-mem interface

kbuild test robot lkp at intel.com
Mon Apr 1 07:01:17 PDT 2019


Hi Boris,

I love your patch! Yet something to improve:

[auto build test ERROR on char-misc/char-misc-testing]
[also build test ERROR on v5.1-rc3 next-20190401]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Boris-Brezillon/eeprom-at25-Convert-the-driver-to-the-spi-mem-interface/20190401-160450
config: x86_64-randconfig-m3-201913 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/misc/eeprom/at25.o: In function `at25_rdsr':
>> drivers/misc/eeprom/at25.c:130: undefined reference to `spi_mem_exec_op'
   drivers/misc/eeprom/at25.o: In function `at25_ee_read':
>> drivers/misc/eeprom/at25.c:178: undefined reference to `spi_mem_dirmap_read'
   drivers/misc/eeprom/at25.o: In function `at25_create_dirmaps':
>> drivers/misc/eeprom/at25.c:86: undefined reference to `devm_spi_mem_dirmap_create'
   drivers/misc/eeprom/at25.c:94: undefined reference to `devm_spi_mem_dirmap_create'
   drivers/misc/eeprom/at25.c:106: undefined reference to `devm_spi_mem_dirmap_create'
   drivers/misc/eeprom/at25.c:114: undefined reference to `devm_spi_mem_dirmap_create'
   drivers/misc/eeprom/at25.o: In function `at25_wren':
   drivers/misc/eeprom/at25.c:144: undefined reference to `spi_mem_exec_op'
   drivers/misc/eeprom/at25.o: In function `at25_ee_write':
>> drivers/misc/eeprom/at25.c:240: undefined reference to `spi_mem_dirmap_write'
   drivers/misc/eeprom/at25.o: In function `at25_driver_init':
>> drivers/misc/eeprom/at25.c:468: undefined reference to `spi_mem_driver_register_with_owner'
   drivers/misc/eeprom/at25.o: In function `at25_driver_exit':
>> drivers/misc/eeprom/at25.c:468: undefined reference to `spi_mem_driver_unregister'

vim +130 drivers/misc/eeprom/at25.c

    70	
    71	static int at25_create_dirmaps(struct at25_data *at25)
    72	{
    73		struct spi_mem_dirmap_info info = {
    74			.op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(AT25_READ, 1),
    75					      SPI_MEM_OP_ADDR(at25->addrlen, 0, 1),
    76					      SPI_MEM_OP_NO_DUMMY,
    77					      SPI_MEM_OP_DATA_IN(0, NULL, 1)),
    78			.offset = 0,
    79			.length = at25->chip.byte_len,
    80		};
    81		struct device *dev = &at25->spimem->spi->dev;
    82	
    83		if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
    84			info.length = 256;
    85	
  > 86		at25->dirmap.rdesc[0] = devm_spi_mem_dirmap_create(dev, at25->spimem,
    87								   &info);
    88		if (IS_ERR(at25->dirmap.rdesc[0]))
    89			return PTR_ERR(at25->dirmap.rdesc[0]);
    90	
    91		info.op_tmpl.cmd.opcode = AT25_WRITE;
    92		info.op_tmpl.data.dir = SPI_MEM_DATA_OUT;
    93	
    94		at25->dirmap.wdesc[0] = devm_spi_mem_dirmap_create(dev, at25->spimem,
    95								   &info);
    96		if (IS_ERR(at25->dirmap.wdesc[0]))
    97			return PTR_ERR(at25->dirmap.wdesc[0]);
    98	
    99		if (!(at25->chip.flags & EE_INSTR_BIT3_IS_ADDR))
   100			return 0;
   101	
   102		info.length = at25->chip.byte_len - 256;
   103		info.op_tmpl.cmd.opcode = AT25_READ | AT25_INSTR_BIT3;
   104		info.op_tmpl.data.dir = SPI_MEM_DATA_IN;
   105	
 > 106		at25->dirmap.rdesc[1] = devm_spi_mem_dirmap_create(dev, at25->spimem,
   107								   &info);
   108		if (IS_ERR(at25->dirmap.rdesc[1]))
   109			return PTR_ERR(at25->dirmap.rdesc[1]);
   110	
   111		info.op_tmpl.cmd.opcode = AT25_WRITE | AT25_INSTR_BIT3;
   112		info.op_tmpl.data.dir = SPI_MEM_DATA_OUT;
   113	
   114		at25->dirmap.wdesc[1] = devm_spi_mem_dirmap_create(dev, at25->spimem,
   115								   &info);
   116		if (IS_ERR(at25->dirmap.wdesc[1]))
   117			return PTR_ERR(at25->dirmap.wdesc[1]);
   118	
   119		return 0;
   120	}
   121	
   122	static int at25_rdsr(struct at25_data *at25)
   123	{
   124		struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(AT25_RDSR, 1),
   125						  SPI_MEM_OP_NO_ADDR,
   126						  SPI_MEM_OP_NO_DUMMY,
   127						  SPI_MEM_OP_DATA_IN(1, at25->scratchbuf, 1));
   128		int ret;
   129	
 > 130		ret = spi_mem_exec_op(at25->spimem, &op);
   131		if (ret)
   132			return ret;
   133	
   134		return *((u8 *)at25->scratchbuf);
   135	}
   136	
   137	static int at25_wren(struct at25_data *at25)
   138	{
   139		struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(AT25_WREN, 1),
   140						  SPI_MEM_OP_NO_ADDR,
   141						  SPI_MEM_OP_NO_DUMMY,
   142						  SPI_MEM_OP_NO_DATA);
   143	
   144		return spi_mem_exec_op(at25->spimem, &op);
   145	}
   146	
   147	static int at25_ee_read(void *priv, unsigned int offset,
   148				void *val, size_t count)
   149	{
   150		struct spi_mem_dirmap_desc *desc;
   151		struct at25_data *at25 = priv;
   152		unsigned int dirmap_offset;
   153		ssize_t			status;
   154	
   155		if (unlikely(offset >= at25->chip.byte_len))
   156			return -EINVAL;
   157		if ((offset + count) > at25->chip.byte_len)
   158			count = at25->chip.byte_len - offset;
   159		if (unlikely(!count))
   160			return -EINVAL;
   161	
   162		if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR && offset > 255) {
   163			desc = at25->dirmap.rdesc[1];
   164			dirmap_offset = offset - 256;
   165		} else {
   166			desc = at25->dirmap.rdesc[0];
   167			dirmap_offset = offset;
   168		}
   169	
   170		mutex_lock(&at25->lock);
   171	
   172		/* Read it all at once.
   173		 *
   174		 * REVISIT that's potentially a problem with large chips, if
   175		 * other devices on the bus need to be accessed regularly or
   176		 * this chip is clocked very slowly
   177		 */
 > 178		status = spi_mem_dirmap_read(desc, dirmap_offset, count, val);
   179		dev_dbg(&at25->spimem->spi->dev, "read %zu bytes at %d --> %zd\n",
   180			count, offset, status);
   181	
   182		mutex_unlock(&at25->lock);
   183		return status;
   184	}
   185	
   186	static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count)
   187	{
   188		struct at25_data *at25 = priv;
   189		const char *buf = val;
   190		int			status = 0;
   191		unsigned		buf_size;
   192		u8			*bounce;
   193	
   194		if (unlikely(off >= at25->chip.byte_len))
   195			return -EFBIG;
   196		if ((off + count) > at25->chip.byte_len)
   197			count = at25->chip.byte_len - off;
   198		if (unlikely(!count))
   199			return -EINVAL;
   200	
   201		/* Temp buffer starts with command and address */
   202		buf_size = at25->chip.page_size;
   203		if (buf_size > io_limit)
   204			buf_size = io_limit;
   205		bounce = kmalloc(buf_size, GFP_KERNEL);
   206		if (!bounce)
   207			return -ENOMEM;
   208	
   209		/* For write, rollover is within the page ... so we write at
   210		 * most one page, then manually roll over to the next page.
   211		 */
   212		mutex_lock(&at25->lock);
   213		do {
   214			struct spi_mem_dirmap_desc *desc;
   215			unsigned long	timeout, retries;
   216			unsigned	segment;
   217			unsigned int	dirmap_offset;
   218			int		sr;
   219	
   220			status = at25_wren(at25);
   221			if (status < 0) {
   222				dev_dbg(&at25->spimem->spi->dev, "WREN --> %d\n",
   223					status);
   224				break;
   225			}
   226	
   227			if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR && off > 255) {
   228				desc = at25->dirmap.wdesc[1];
   229				dirmap_offset = off -  256;
   230			} else {
   231				desc = at25->dirmap.wdesc[0];
   232				dirmap_offset = off;
   233			}
   234	
   235			/* Write as much of a page as we can */
   236			segment = buf_size - (dirmap_offset % buf_size);
   237			if (segment > count)
   238				segment = count;
   239			memcpy(bounce, buf, segment);
 > 240			status = spi_mem_dirmap_write(desc, dirmap_offset, segment,
   241						      bounce);
   242			dev_dbg(&at25->spimem->spi->dev,
   243				"write %u bytes at %u --> %d\n",
   244				segment, off, status);
   245			if (status < 0)
   246				break;
   247	
   248			/* REVISIT this should detect (or prevent) failed writes
   249			 * to readonly sections of the EEPROM...
   250			 */
   251	
   252			/* Wait for non-busy status */
   253			timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT);
   254			retries = 0;
   255			do {
   256				sr = at25_rdsr(at25);
   257				if (sr < 0 || (sr & AT25_SR_nRDY)) {
   258					dev_dbg(&at25->spimem->spi->dev,
   259						"rdsr --> %d (%02x)\n", sr, sr);
   260					/* at HZ=100, this is sloooow */
   261					msleep(1);
   262					continue;
   263				}
   264				if (!(sr & AT25_SR_nRDY))
   265					break;
   266			} while (retries++ < 3 || time_before_eq(jiffies, timeout));
   267	
   268			if ((sr < 0) || (sr & AT25_SR_nRDY)) {
   269				dev_err(&at25->spimem->spi->dev,
   270					"write %u bytes offset %u, timeout after %u msecs\n",
   271					segment, off,
   272					jiffies_to_msecs(jiffies -
   273						(timeout - EE_TIMEOUT)));
   274				status = -ETIMEDOUT;
   275				break;
   276			}
   277	
   278			off += segment;
   279			buf += segment;
   280			count -= segment;
   281	
   282		} while (count > 0);
   283	
   284		mutex_unlock(&at25->lock);
   285	
   286		kfree(bounce);
   287		return status;
   288	}
   289	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 35405 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20190401/8efd1cf0/attachment-0001.gz>


More information about the linux-mtd mailing list