tree:
https://github.com/ambarus/linux-0day spi-nor/next-otp-ammend-check-link-err
head: bf51641a17e761b318f490fe04adc7f5359c0d37
commit: 6081b3c35765470cd8188c26cc2497c74bed9a87 [11/14] mtd: spi-nor: add OTP support
config: i386-randconfig-c021-20210330 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
#
https://github.com/ambarus/linux-0day/commit/6081b3c35765470cd8188c26cc24...
git remote add ambarus
https://github.com/ambarus/linux-0day
git fetch --no-tags ambarus spi-nor/next-otp-ammend-check-link-err
git checkout 6081b3c35765470cd8188c26cc2497c74bed9a87
# save the attached .config to linux build tree
make W=1 ARCH=i386
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp(a)intel.com>
All errors (new ones prefixed by >>):
ld: drivers/mtd/spi-nor/otp.o: in function `spi_nor_mtd_otp_lock':
> drivers/mtd/spi-nor/otp.c:171: undefined reference to
`__moddi3'
ld: drivers/mtd/spi-nor/otp.o: in function
`spi_nor_otp_offset_to_region':
> drivers/mtd/spi-nor/otp.c:40: undefined reference to
`__divdi3'
> ld: drivers/mtd/spi-nor/otp.c:40: undefined reference to `__divdi3'
vim +171 drivers/mtd/spi-nor/otp.c
37
38 static unsigned int spi_nor_otp_offset_to_region(struct spi_nor *nor, loff_t ofs)
39 {
40 return ofs / spi_nor_otp_region_len(nor);
41 }
42
43 static int spi_nor_mtd_otp_info(struct mtd_info *mtd, size_t len,
44 size_t *retlen, struct otp_info *buf)
45 {
46 struct spi_nor *nor = mtd_to_spi_nor(mtd);
47 const struct spi_nor_otp_ops *ops = nor->params->otp.ops;
48 unsigned int n_regions = spi_nor_otp_n_regions(nor);
49 unsigned int i;
50 int ret, locked;
51
52 if (len < n_regions * sizeof(*buf))
53 return -ENOSPC;
54
55 ret = spi_nor_lock_and_prep(nor);
56 if (ret)
57 return ret;
58
59 for (i = 0; i < n_regions; i++) {
60 buf->start = spi_nor_otp_region_to_offset(nor, i);
61 buf->length = spi_nor_otp_region_len(nor);
62
63 locked = ops->is_locked(nor, i);
64 if (locked < 0) {
65 ret = locked;
66 goto out;
67 }
68
69 buf->locked = !!locked;
70 buf++;
71 }
72
73 *retlen = n_regions * sizeof(*buf);
74
75 out:
76 spi_nor_unlock_and_unprep(nor);
77
78 return ret;
79 }
80
81 static int spi_nor_mtd_otp_read_write(struct mtd_info *mtd, loff_t ofs,
82 size_t total_len, size_t *retlen,
83 u8 *buf, bool is_write)
84 {
85 struct spi_nor *nor = mtd_to_spi_nor(mtd);
86 const struct spi_nor_otp_ops *ops = nor->params->otp.ops;
87 const size_t rlen = spi_nor_otp_region_len(nor);
88 loff_t rstart, rofs;
89 unsigned int region;
90 size_t len;
91 int ret;
92
93 if (ofs < 0 || ofs >= spi_nor_otp_size(nor))
94 return 0;
95
96 ret = spi_nor_lock_and_prep(nor);
97 if (ret)
98 return ret;
99
100 /* don't access beyond the end */
101 total_len = min_t(size_t, total_len, spi_nor_otp_size(nor) - ofs);
102
103 *retlen = 0;
104 while (total_len) {
105 /*
106 * The OTP regions are mapped into a contiguous area starting
107 * at 0 as expected by the MTD layer. This will map the MTD
108 * file offsets to the address of an OTP region as used in the
109 * actual SPI commands.
110 */
111 region = spi_nor_otp_offset_to_region(nor, ofs);
112 rstart = spi_nor_otp_region_start(nor, region);
113
114 /*
115 * The size of a OTP region is expected to be a power of two,
116 * thus we can just mask the lower bits and get the offset into
117 * a region.
118 */
119 rofs = ofs & (rlen - 1);
120
121 /* don't access beyond one OTP region */
122 len = min_t(size_t, total_len, rlen - rofs);
123
124 if (is_write)
125 ret = ops->write(nor, rstart + rofs, len, buf);
126 else
127 ret = ops->read(nor, rstart + rofs, len, buf);
128 if (ret == 0)
129 ret = -EIO;
130 if (ret < 0)
131 goto out;
132
133 *retlen += ret;
134 ofs += ret;
135 buf += ret;
136 total_len -= ret;
137 }
138 ret = 0;
139
140 out:
141 spi_nor_unlock_and_unprep(nor);
142 return ret;
143 }
144
145 static int spi_nor_mtd_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
146 size_t *retlen, u8 *buf)
147 {
148 return spi_nor_mtd_otp_read_write(mtd, from, len, retlen, buf, false);
149 }
150
151 static int spi_nor_mtd_otp_write(struct mtd_info *mtd, loff_t to, size_t len,
152 size_t *retlen, u8 *buf)
153 {
154 return spi_nor_mtd_otp_read_write(mtd, to, len, retlen, buf, true);
155 }
156
157 static int spi_nor_mtd_otp_lock(struct mtd_info *mtd, loff_t from, size_t len)
158 {
159 struct spi_nor *nor = mtd_to_spi_nor(mtd);
160 const struct spi_nor_otp_ops *ops = nor->params->otp.ops;
161 unsigned int region;
162 int ret;
163
164 if (from < 0 || (from + len) > spi_nor_otp_size(nor))
165 return -EINVAL;
166
167 /* the user has to explicitly ask for whole regions */
168 if (len % spi_nor_otp_region_len(nor))
169 return -EINVAL;
170
171 if (from % spi_nor_otp_region_len(nor))
172 return
-EINVAL;
173
174 ret = spi_nor_lock_and_prep(nor);
175 if (ret)
176 return ret;
177
178 while (len) {
179 region = spi_nor_otp_offset_to_region(nor, from);
180 ret = ops->lock(nor, region);
181 if (ret)
182 goto out;
183
184 len -= spi_nor_otp_region_len(nor);
185 from += spi_nor_otp_region_len(nor);
186 }
187
188 out:
189 spi_nor_unlock_and_unprep(nor);
190
191 return ret;
192 }
193
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org