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

Attachment: .config.gz
Description: application/gzip

Reply via email to