Re: [PATCH] eeprom: at25: Convert the driver to the spi-mem interface
From: kbuild test robot
Date: Mon Apr 01 2019 - 10:01:34 EST
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