1 /* 2 * Core registration and callback routines for MTD 3 * drivers and users. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10 #include <linux/mtd/mtd.h> 11 #include <linux/compat.h> 12 #include <ubi_uboot.h> 13 14 struct mtd_info *mtd_table[MAX_MTD_DEVICES]; 15 16 int add_mtd_device(struct mtd_info *mtd) 17 { 18 int i; 19 20 BUG_ON(mtd->writesize == 0); 21 22 for (i = 0; i < MAX_MTD_DEVICES; i++) 23 if (!mtd_table[i]) { 24 mtd_table[i] = mtd; 25 mtd->index = i; 26 mtd->usecount = 0; 27 28 /* default value if not set by driver */ 29 if (mtd->bitflip_threshold == 0) 30 mtd->bitflip_threshold = mtd->ecc_strength; 31 32 33 /* No need to get a refcount on the module containing 34 the notifier, since we hold the mtd_table_mutex */ 35 36 /* We _know_ we aren't being removed, because 37 our caller is still holding us here. So none 38 of this try_ nonsense, and no bitching about it 39 either. :) */ 40 return 0; 41 } 42 43 return 1; 44 } 45 46 /** 47 * del_mtd_device - unregister an MTD device 48 * @mtd: pointer to MTD device info structure 49 * 50 * Remove a device from the list of MTD devices present in the system, 51 * and notify each currently active MTD 'user' of its departure. 52 * Returns zero on success or 1 on failure, which currently will happen 53 * if the requested device does not appear to be present in the list. 54 */ 55 int del_mtd_device(struct mtd_info *mtd) 56 { 57 int ret; 58 59 if (mtd_table[mtd->index] != mtd) { 60 ret = -ENODEV; 61 } else if (mtd->usecount) { 62 printk(KERN_NOTICE "Removing MTD device #%d (%s)" 63 " with use count %d\n", 64 mtd->index, mtd->name, mtd->usecount); 65 ret = -EBUSY; 66 } else { 67 /* No need to get a refcount on the module containing 68 * the notifier, since we hold the mtd_table_mutex */ 69 mtd_table[mtd->index] = NULL; 70 71 ret = 0; 72 } 73 74 return ret; 75 } 76 77 /** 78 * get_mtd_device - obtain a validated handle for an MTD device 79 * @mtd: last known address of the required MTD device 80 * @num: internal device number of the required MTD device 81 * 82 * Given a number and NULL address, return the num'th entry in the device 83 * table, if any. Given an address and num == -1, search the device table 84 * for a device with that address and return if it's still present. Given 85 * both, return the num'th driver only if its address matches. Return 86 * error code if not. 87 */ 88 struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) 89 { 90 struct mtd_info *ret = NULL; 91 int i, err = -ENODEV; 92 93 if (num == -1) { 94 for (i = 0; i < MAX_MTD_DEVICES; i++) 95 if (mtd_table[i] == mtd) 96 ret = mtd_table[i]; 97 } else if (num < MAX_MTD_DEVICES) { 98 ret = mtd_table[num]; 99 if (mtd && mtd != ret) 100 ret = NULL; 101 } 102 103 if (!ret) 104 goto out_unlock; 105 106 ret->usecount++; 107 return ret; 108 109 out_unlock: 110 return ERR_PTR(err); 111 } 112 113 /** 114 * get_mtd_device_nm - obtain a validated handle for an MTD device by 115 * device name 116 * @name: MTD device name to open 117 * 118 * This function returns MTD device description structure in case of 119 * success and an error code in case of failure. 120 */ 121 struct mtd_info *get_mtd_device_nm(const char *name) 122 { 123 int i, err = -ENODEV; 124 struct mtd_info *mtd = NULL; 125 126 for (i = 0; i < MAX_MTD_DEVICES; i++) { 127 if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) { 128 mtd = mtd_table[i]; 129 break; 130 } 131 } 132 133 if (!mtd) 134 goto out_unlock; 135 136 mtd->usecount++; 137 return mtd; 138 139 out_unlock: 140 return ERR_PTR(err); 141 } 142 143 void put_mtd_device(struct mtd_info *mtd) 144 { 145 int c; 146 147 c = --mtd->usecount; 148 BUG_ON(c < 0); 149 } 150 151 #if defined(CONFIG_CMD_MTDPARTS_SPREAD) 152 /** 153 * mtd_get_len_incl_bad 154 * 155 * Check if length including bad blocks fits into device. 156 * 157 * @param mtd an MTD device 158 * @param offset offset in flash 159 * @param length image length 160 * @return image length including bad blocks in *len_incl_bad and whether or not 161 * the length returned was truncated in *truncated 162 */ 163 void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset, 164 const uint64_t length, uint64_t *len_incl_bad, 165 int *truncated) 166 { 167 *truncated = 0; 168 *len_incl_bad = 0; 169 170 if (!mtd->block_isbad) { 171 *len_incl_bad = length; 172 return; 173 } 174 175 uint64_t len_excl_bad = 0; 176 uint64_t block_len; 177 178 while (len_excl_bad < length) { 179 if (offset >= mtd->size) { 180 *truncated = 1; 181 return; 182 } 183 184 block_len = mtd->erasesize - (offset & (mtd->erasesize - 1)); 185 186 if (!mtd->block_isbad(mtd, offset & ~(mtd->erasesize - 1))) 187 len_excl_bad += block_len; 188 189 *len_incl_bad += block_len; 190 offset += block_len; 191 } 192 } 193 #endif /* defined(CONFIG_CMD_MTDPARTS_SPREAD) */ 194 195 /* 196 * Erase is an asynchronous operation. Device drivers are supposed 197 * to call instr->callback() whenever the operation completes, even 198 * if it completes with a failure. 199 * Callers are supposed to pass a callback function and wait for it 200 * to be called before writing to the block. 201 */ 202 int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) 203 { 204 if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr) 205 return -EINVAL; 206 if (!(mtd->flags & MTD_WRITEABLE)) 207 return -EROFS; 208 instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; 209 if (!instr->len) { 210 instr->state = MTD_ERASE_DONE; 211 mtd_erase_callback(instr); 212 return 0; 213 } 214 return mtd->_erase(mtd, instr); 215 } 216 217 int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, 218 u_char *buf) 219 { 220 if (from < 0 || from > mtd->size || len > mtd->size - from) 221 return -EINVAL; 222 if (!len) 223 return 0; 224 return mtd->_read(mtd, from, len, retlen, buf); 225 } 226 227 int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 228 const u_char *buf) 229 { 230 *retlen = 0; 231 if (to < 0 || to > mtd->size || len > mtd->size - to) 232 return -EINVAL; 233 if (!mtd->_write || !(mtd->flags & MTD_WRITEABLE)) 234 return -EROFS; 235 if (!len) 236 return 0; 237 return mtd->_write(mtd, to, len, retlen, buf); 238 } 239 240 /* 241 * In blackbox flight recorder like scenarios we want to make successful writes 242 * in interrupt context. panic_write() is only intended to be called when its 243 * known the kernel is about to panic and we need the write to succeed. Since 244 * the kernel is not going to be running for much longer, this function can 245 * break locks and delay to ensure the write succeeds (but not sleep). 246 */ 247 int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, 248 const u_char *buf) 249 { 250 *retlen = 0; 251 if (!mtd->_panic_write) 252 return -EOPNOTSUPP; 253 if (to < 0 || to > mtd->size || len > mtd->size - to) 254 return -EINVAL; 255 if (!(mtd->flags & MTD_WRITEABLE)) 256 return -EROFS; 257 if (!len) 258 return 0; 259 return mtd->_panic_write(mtd, to, len, retlen, buf); 260 } 261 262 int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops) 263 { 264 ops->retlen = ops->oobretlen = 0; 265 if (!mtd->_read_oob) 266 return -EOPNOTSUPP; 267 return mtd->_read_oob(mtd, from, ops); 268 } 269 270 /* 271 * Method to access the protection register area, present in some flash 272 * devices. The user data is one time programmable but the factory data is read 273 * only. 274 */ 275 int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf, 276 size_t len) 277 { 278 if (!mtd->_get_fact_prot_info) 279 return -EOPNOTSUPP; 280 if (!len) 281 return 0; 282 return mtd->_get_fact_prot_info(mtd, buf, len); 283 } 284 285 int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 286 size_t *retlen, u_char *buf) 287 { 288 *retlen = 0; 289 if (!mtd->_read_fact_prot_reg) 290 return -EOPNOTSUPP; 291 if (!len) 292 return 0; 293 return mtd->_read_fact_prot_reg(mtd, from, len, retlen, buf); 294 } 295 296 int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf, 297 size_t len) 298 { 299 if (!mtd->_get_user_prot_info) 300 return -EOPNOTSUPP; 301 if (!len) 302 return 0; 303 return mtd->_get_user_prot_info(mtd, buf, len); 304 } 305 306 int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len, 307 size_t *retlen, u_char *buf) 308 { 309 *retlen = 0; 310 if (!mtd->_read_user_prot_reg) 311 return -EOPNOTSUPP; 312 if (!len) 313 return 0; 314 return mtd->_read_user_prot_reg(mtd, from, len, retlen, buf); 315 } 316 317 int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len, 318 size_t *retlen, u_char *buf) 319 { 320 *retlen = 0; 321 if (!mtd->_write_user_prot_reg) 322 return -EOPNOTSUPP; 323 if (!len) 324 return 0; 325 return mtd->_write_user_prot_reg(mtd, to, len, retlen, buf); 326 } 327 328 int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len) 329 { 330 if (!mtd->_lock_user_prot_reg) 331 return -EOPNOTSUPP; 332 if (!len) 333 return 0; 334 return mtd->_lock_user_prot_reg(mtd, from, len); 335 } 336 337 /* Chip-supported device locking */ 338 int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 339 { 340 if (!mtd->_lock) 341 return -EOPNOTSUPP; 342 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) 343 return -EINVAL; 344 if (!len) 345 return 0; 346 return mtd->_lock(mtd, ofs, len); 347 } 348 349 int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) 350 { 351 if (!mtd->_unlock) 352 return -EOPNOTSUPP; 353 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) 354 return -EINVAL; 355 if (!len) 356 return 0; 357 return mtd->_unlock(mtd, ofs, len); 358 } 359 360 int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) 361 { 362 if (!mtd->_block_isbad) 363 return 0; 364 if (ofs < 0 || ofs > mtd->size) 365 return -EINVAL; 366 return mtd->_block_isbad(mtd, ofs); 367 } 368 369 int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) 370 { 371 if (!mtd->_block_markbad) 372 return -EOPNOTSUPP; 373 if (ofs < 0 || ofs > mtd->size) 374 return -EINVAL; 375 if (!(mtd->flags & MTD_WRITEABLE)) 376 return -EROFS; 377 return mtd->_block_markbad(mtd, ofs); 378 } 379 380