Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[MTD][NOR] Add physical address to point() method

Adding the ability to get a physical address from point() in addition
to virtual address. This physical address is required for XIP of
userspace code from flash.

Signed-off-by: Jared Hulbert <jaredeh@gmail.com>
Reviewed-by: Jörn Engel <joern@logfs.org>
Acked-by: Nicolas Pitre <nico@cam.org>
Acked-by: Greg Ungerer <gerg@uclinux.org>
Signed-off-by: David Woodhouse <dwmw2@infradead.org>

authored by

Jared Hulbert and committed by
David Woodhouse
a98889f3 27c72b04

+77 -51
+8 -6
drivers/mtd/chips/cfi_cmdset_0001.c
··· 82 82 static int cfi_intelext_partition_fixup(struct mtd_info *, struct cfi_private **); 83 83 84 84 static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, 85 - size_t *retlen, u_char **mtdbuf); 86 - static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, 87 - size_t len); 85 + size_t *retlen, void **virt, resource_size_t *phys); 86 + static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len); 88 87 89 88 static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode); 90 89 static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode); ··· 1239 1240 return ret; 1240 1241 } 1241 1242 1242 - static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf) 1243 + static int cfi_intelext_point(struct mtd_info *mtd, loff_t from, size_t len, 1244 + size_t *retlen, void **virt, resource_size_t *phys) 1243 1245 { 1244 1246 struct map_info *map = mtd->priv; 1245 1247 struct cfi_private *cfi = map->fldrv_priv; ··· 1257 1257 chipnum = (from >> cfi->chipshift); 1258 1258 ofs = from - (chipnum << cfi->chipshift); 1259 1259 1260 - *mtdbuf = (void *)map->virt + cfi->chips[chipnum].start + ofs; 1260 + *virt = map->virt + cfi->chips[chipnum].start + ofs; 1261 1261 *retlen = 0; 1262 + if (phys) 1263 + *phys = map->phys + cfi->chips[chipnum].start + ofs; 1262 1264 1263 1265 while (len) { 1264 1266 unsigned long thislen; ··· 1293 1291 return 0; 1294 1292 } 1295 1293 1296 - static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) 1294 + static void cfi_intelext_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 1297 1295 { 1298 1296 struct map_info *map = mtd->priv; 1299 1297 struct cfi_private *cfi = map->fldrv_priv;
+7 -4
drivers/mtd/devices/mtdram.c
··· 48 48 } 49 49 50 50 static int ram_point(struct mtd_info *mtd, loff_t from, size_t len, 51 - size_t *retlen, u_char **mtdbuf) 51 + size_t *retlen, void **virt, resource_size_t *phys) 52 52 { 53 53 if (from + len > mtd->size) 54 54 return -EINVAL; 55 55 56 - *mtdbuf = mtd->priv + from; 56 + /* can we return a physical address with this driver? */ 57 + if (phys) 58 + return -EINVAL; 59 + 60 + *virt = mtd->priv + from; 57 61 *retlen = len; 58 62 return 0; 59 63 } 60 64 61 - static void ram_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from, 62 - size_t len) 65 + static void ram_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 63 66 { 64 67 } 65 68
+7 -6
drivers/mtd/devices/phram.c
··· 57 57 } 58 58 59 59 static int phram_point(struct mtd_info *mtd, loff_t from, size_t len, 60 - size_t *retlen, u_char **mtdbuf) 60 + size_t *retlen, void **virt, resource_size_t *phys) 61 61 { 62 - u_char *start = mtd->priv; 63 - 64 62 if (from + len > mtd->size) 65 63 return -EINVAL; 66 64 67 - *mtdbuf = start + from; 65 + /* can we return a physical address with this driver? */ 66 + if (phys) 67 + return -EINVAL; 68 + 69 + *virt = mtd->priv + from; 68 70 *retlen = len; 69 71 return 0; 70 72 } 71 73 72 - static void phram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, 73 - size_t len) 74 + static void phram_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 74 75 { 75 76 } 76 77
+17 -10
drivers/mtd/devices/pmc551.c
··· 134 134 eoff_lo = end & (priv->asize - 1); 135 135 soff_lo = instr->addr & (priv->asize - 1); 136 136 137 - pmc551_point(mtd, instr->addr, instr->len, &retlen, &ptr); 137 + pmc551_point(mtd, instr->addr, instr->len, &retlen, 138 + (void **)&ptr, NULL); 138 139 139 140 if (soff_hi == eoff_hi || mtd->size == priv->asize) { 140 141 /* The whole thing fits within one access, so just one shot ··· 155 154 } 156 155 soff_hi += priv->asize; 157 156 pmc551_point(mtd, (priv->base_map0 | soff_hi), 158 - priv->asize, &retlen, &ptr); 157 + priv->asize, &retlen, 158 + (void **)&ptr, NULL); 159 159 } 160 160 memset(ptr, 0xff, eoff_lo); 161 161 } ··· 172 170 } 173 171 174 172 static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, 175 - size_t * retlen, u_char ** mtdbuf) 173 + size_t *retlen, void **virt, resource_size_t *phys) 176 174 { 177 175 struct mypriv *priv = mtd->priv; 178 176 u32 soff_hi; ··· 190 188 return -EINVAL; 191 189 } 192 190 191 + /* can we return a physical address with this driver? */ 192 + if (phys) 193 + return -EINVAL; 194 + 193 195 soff_hi = from & ~(priv->asize - 1); 194 196 soff_lo = from & (priv->asize - 1); 195 197 ··· 204 198 priv->curr_map0 = soff_hi; 205 199 } 206 200 207 - *mtdbuf = priv->start + soff_lo; 201 + *virt = priv->start + soff_lo; 208 202 *retlen = len; 209 203 return 0; 210 204 } 211 205 212 - static void pmc551_unpoint(struct mtd_info *mtd, u_char * addr, loff_t from, 213 - size_t len) 206 + static void pmc551_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 214 207 { 215 208 #ifdef CONFIG_MTD_PMC551_DEBUG 216 209 printk(KERN_DEBUG "pmc551_unpoint()\n"); ··· 247 242 soff_lo = from & (priv->asize - 1); 248 243 eoff_lo = end & (priv->asize - 1); 249 244 250 - pmc551_point(mtd, from, len, retlen, &ptr); 245 + pmc551_point(mtd, from, len, retlen, (void **)&ptr, NULL); 251 246 252 247 if (soff_hi == eoff_hi) { 253 248 /* The whole thing fits within one access, so just one shot ··· 268 263 goto out; 269 264 } 270 265 soff_hi += priv->asize; 271 - pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr); 266 + pmc551_point(mtd, soff_hi, priv->asize, retlen, 267 + (void **)&ptr, NULL); 272 268 } 273 269 memcpy(copyto, ptr, eoff_lo); 274 270 copyto += eoff_lo; ··· 314 308 soff_lo = to & (priv->asize - 1); 315 309 eoff_lo = end & (priv->asize - 1); 316 310 317 - pmc551_point(mtd, to, len, retlen, &ptr); 311 + pmc551_point(mtd, to, len, retlen, (void **)&ptr, NULL); 318 312 319 313 if (soff_hi == eoff_hi) { 320 314 /* The whole thing fits within one access, so just one shot ··· 335 329 goto out; 336 330 } 337 331 soff_hi += priv->asize; 338 - pmc551_point(mtd, soff_hi, priv->asize, retlen, &ptr); 332 + pmc551_point(mtd, soff_hi, priv->asize, retlen, 333 + (void **)&ptr, NULL); 339 334 } 340 335 memcpy(ptr, copyfrom, eoff_lo); 341 336 copyfrom += eoff_lo;
+10 -5
drivers/mtd/devices/slram.c
··· 76 76 static slram_mtd_list_t *slram_mtdlist = NULL; 77 77 78 78 static int slram_erase(struct mtd_info *, struct erase_info *); 79 - static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, u_char **); 80 - static void slram_unpoint(struct mtd_info *, u_char *, loff_t, size_t); 79 + static int slram_point(struct mtd_info *, loff_t, size_t, size_t *, void **, 80 + resource_size_t *); 81 + static void slram_unpoint(struct mtd_info *, loff_t, size_t); 81 82 static int slram_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); 82 83 static int slram_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); 83 84 ··· 105 104 } 106 105 107 106 static int slram_point(struct mtd_info *mtd, loff_t from, size_t len, 108 - size_t *retlen, u_char **mtdbuf) 107 + size_t *retlen, void **virt, resource_size_t *phys) 109 108 { 110 109 slram_priv_t *priv = mtd->priv; 110 + 111 + /* can we return a physical address with this driver? */ 112 + if (phys) 113 + return -EINVAL; 111 114 112 115 if (from + len > mtd->size) 113 116 return -EINVAL; 114 117 115 - *mtdbuf = priv->start + from; 118 + *virt = priv->start + from; 116 119 *retlen = len; 117 120 return(0); 118 121 } 119 122 120 - static void slram_unpoint(struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) 123 + static void slram_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 121 124 { 122 125 } 123 126
+4 -2
drivers/mtd/maps/uclinux.c
··· 40 40 /****************************************************************************/ 41 41 42 42 int uclinux_point(struct mtd_info *mtd, loff_t from, size_t len, 43 - size_t *retlen, u_char **mtdbuf) 43 + size_t *retlen, void **virt, resource_size_t *phys) 44 44 { 45 45 struct map_info *map = mtd->priv; 46 - *mtdbuf = (u_char *) (map->virt + ((int) from)); 46 + *virt = map->virt + from; 47 + if (phys) 48 + *phys = map->phys + from; 47 49 *retlen = len; 48 50 return(0); 49 51 }
+4 -4
drivers/mtd/mtdpart.c
··· 68 68 } 69 69 70 70 static int part_point (struct mtd_info *mtd, loff_t from, size_t len, 71 - size_t *retlen, u_char **buf) 71 + size_t *retlen, void **virt, resource_size_t *phys) 72 72 { 73 73 struct mtd_part *part = PART(mtd); 74 74 if (from >= mtd->size) ··· 76 76 else if (from + len > mtd->size) 77 77 len = mtd->size - from; 78 78 return part->master->point (part->master, from + part->offset, 79 - len, retlen, buf); 79 + len, retlen, virt, phys); 80 80 } 81 81 82 - static void part_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len) 82 + static void part_unpoint(struct mtd_info *mtd, loff_t from, size_t len) 83 83 { 84 84 struct mtd_part *part = PART(mtd); 85 85 86 - part->master->unpoint (part->master, addr, from + part->offset, len); 86 + part->master->unpoint(part->master, from + part->offset, len); 87 87 } 88 88 89 89 static int part_read_oob(struct mtd_info *mtd, loff_t from,
+4 -3
fs/jffs2/erase.c
··· 332 332 if (c->mtd->point) { 333 333 unsigned long *wordebuf; 334 334 335 - ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, &retlen, (unsigned char **)&ebuf); 335 + ret = c->mtd->point(c->mtd, jeb->offset, c->sector_size, 336 + &retlen, &ebuf, NULL); 336 337 if (ret) { 337 338 D1(printk(KERN_DEBUG "MTD point failed %d\n", ret)); 338 339 goto do_flash_read; ··· 341 340 if (retlen < c->sector_size) { 342 341 /* Don't muck about if it won't let us point to the whole erase sector */ 343 342 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", retlen)); 344 - c->mtd->unpoint(c->mtd, ebuf, jeb->offset, retlen); 343 + c->mtd->unpoint(c->mtd, jeb->offset, retlen); 345 344 goto do_flash_read; 346 345 } 347 346 wordebuf = ebuf-sizeof(*wordebuf); ··· 350 349 if (*++wordebuf != ~0) 351 350 break; 352 351 } while(--retlen); 353 - c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size); 352 + c->mtd->unpoint(c->mtd, jeb->offset, c->sector_size); 354 353 if (retlen) { 355 354 printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n", 356 355 *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf));
+5 -4
fs/jffs2/readinode.c
··· 63 63 /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), 64 64 * adding and jffs2_flash_read_end() interface. */ 65 65 if (c->mtd->point) { 66 - err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); 66 + err = c->mtd->point(c->mtd, ofs, len, &retlen, 67 + (void **)&buffer, NULL); 67 68 if (!err && retlen < len) { 68 69 JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); 69 - c->mtd->unpoint(c->mtd, buffer, ofs, retlen); 70 + c->mtd->unpoint(c->mtd, ofs, retlen); 70 71 } else if (err) 71 72 JFFS2_WARNING("MTD point failed: error code %d.\n", err); 72 73 else ··· 101 100 kfree(buffer); 102 101 #ifndef __ECOS 103 102 else 104 - c->mtd->unpoint(c->mtd, buffer, ofs, len); 103 + c->mtd->unpoint(c->mtd, ofs, len); 105 104 #endif 106 105 107 106 if (crc != tn->data_crc) { ··· 137 136 kfree(buffer); 138 137 #ifndef __ECOS 139 138 else 140 - c->mtd->unpoint(c->mtd, buffer, ofs, len); 139 + c->mtd->unpoint(c->mtd, ofs, len); 141 140 #endif 142 141 return err; 143 142 }
+4 -3
fs/jffs2/scan.c
··· 97 97 size_t pointlen; 98 98 99 99 if (c->mtd->point) { 100 - ret = c->mtd->point (c->mtd, 0, c->mtd->size, &pointlen, &flashbuf); 100 + ret = c->mtd->point(c->mtd, 0, c->mtd->size, &pointlen, 101 + (void **)&flashbuf, NULL); 101 102 if (!ret && pointlen < c->mtd->size) { 102 103 /* Don't muck about if it won't let us point to the whole flash */ 103 104 D1(printk(KERN_DEBUG "MTD point returned len too short: 0x%zx\n", pointlen)); 104 - c->mtd->unpoint(c->mtd, flashbuf, 0, pointlen); 105 + c->mtd->unpoint(c->mtd, 0, pointlen); 105 106 flashbuf = NULL; 106 107 } 107 108 if (ret) ··· 268 267 kfree(flashbuf); 269 268 #ifndef __ECOS 270 269 else 271 - c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); 270 + c->mtd->unpoint(c->mtd, 0, c->mtd->size); 272 271 #endif 273 272 if (s) 274 273 kfree(s);
+4 -2
include/linux/mtd/mtd.h
··· 143 143 int (*erase) (struct mtd_info *mtd, struct erase_info *instr); 144 144 145 145 /* This stuff for eXecute-In-Place */ 146 - int (*point) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); 146 + /* phys is optional and may be set to NULL */ 147 + int (*point) (struct mtd_info *mtd, loff_t from, size_t len, 148 + size_t *retlen, void **virt, resource_size_t *phys); 147 149 148 150 /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ 149 - void (*unpoint) (struct mtd_info *mtd, u_char * addr, loff_t from, size_t len); 151 + void (*unpoint) (struct mtd_info *mtd, loff_t from, size_t len); 150 152 151 153 152 154 int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+3 -2
include/linux/mtd/pmc551.h
··· 36 36 * Function Prototypes 37 37 */ 38 38 static int pmc551_erase(struct mtd_info *, struct erase_info *); 39 - static void pmc551_unpoint(struct mtd_info *, u_char *, loff_t, size_t); 40 - static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); 39 + static void pmc551_unpoint(struct mtd_info *, loff_t, size_t); 40 + static int pmc551_point(struct mtd_info *mtd, loff_t from, size_t len, 41 + size_t *retlen, void **virt, resource_size_t *phys); 41 42 static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); 42 43 static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); 43 44