?? mtd.patch
字號:
+ if (chip->state != mode) { /* Someone's suspended the write. Sleep */ DECLARE_WAITQUEUE(wait, current); @@ -1331,23 +1311,22 @@ /* OK Still waiting */ if (time_after(jiffies, timeo)) {+ map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; xip_enable(map, chip, adr);- printk(KERN_ERR "waiting for chip to be ready timed out in word write\n");+ printk(KERN_ERR "%s: word write error (status timeout)\n", map->name); ret = -EIO; goto out; } /* Latency issues. Drop the lock, wait a while and retry */- spin_unlock(chip->mutex); z++; UDELAY(map, chip, adr, 1);- spin_lock(chip->mutex); } if (!z) { chip->word_write_time--; if (!chip->word_write_time)- chip->word_write_time++;+ chip->word_write_time = 1; } if (z > 1) chip->word_write_time++;@@ -1355,19 +1334,31 @@ /* Done and happy. */ chip->state = FL_STATUS; - /* check for lock bit */- if (map_word_bitsset(map, status, CMD(0x02))) {- /* clear status */+ /* check for errors */+ if (map_word_bitsset(map, status, CMD(0x1a))) {+ unsigned long chipstatus = MERGESTATUS(status);++ /* reset status */ map_write(map, CMD(0x50), adr);- /* put back into read status register mode */ map_write(map, CMD(0x70), adr);- ret = -EROFS;+ xip_enable(map, chip, adr);++ if (chipstatus & 0x02) {+ ret = -EROFS;+ } else if (chipstatus & 0x08) {+ printk(KERN_ERR "%s: word write error (bad VPP)\n", map->name);+ ret = -EIO;+ } else {+ printk(KERN_ERR "%s: word write error (status 0x%lx)\n", map->name, chipstatus);+ ret = -EINVAL;+ }++ goto out; } xip_enable(map, chip, adr); out: put_chip(map, chip, adr); spin_unlock(chip->mutex);- return ret; } @@ -1399,7 +1390,7 @@ datum = map_word_load_partial(map, datum, buf, gap, n); ret = do_write_oneword(map, &cfi->chips[chipnum],- bus_ofs, datum);+ bus_ofs, datum, FL_WRITING); if (ret) return ret; @@ -1420,7 +1411,7 @@ map_word datum = map_word_load(map, buf); ret = do_write_oneword(map, &cfi->chips[chipnum],- ofs, datum);+ ofs, datum, FL_WRITING); if (ret) return ret; @@ -1444,7 +1435,7 @@ datum = map_word_load_partial(map, datum, buf, 0, len); ret = do_write_oneword(map, &cfi->chips[chipnum],- ofs, datum);+ ofs, datum, FL_WRITING); if (ret) return ret; @@ -1456,19 +1447,23 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, - unsigned long adr, const u_char *buf, int len)+ unsigned long adr, const struct kvec **pvec,+ unsigned long *pvec_seek, int len) { struct cfi_private *cfi = map->fldrv_priv;- map_word status, status_OK;+ map_word status, status_OK, write_cmd, datum; unsigned long cmd_adr, timeo;- int wbufsize, z, ret=0, bytes, words;+ int wbufsize, z, ret=0, word_gap, words;+ const struct kvec *vec;+ unsigned long vec_seek; wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; adr += chip->start; cmd_adr = adr & ~(wbufsize-1);- + /* Let's determine this according to the interleave only once */ status_OK = CMD(0x80);+ write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); spin_lock(chip->mutex); ret = get_chip(map, chip, cmd_adr, FL_WRITING);@@ -1500,15 +1495,13 @@ z = 0; for (;;) {- map_write(map, CMD(0xe8), cmd_adr);+ map_write(map, write_cmd, cmd_adr); status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) break; - spin_unlock(chip->mutex); UDELAY(map, chip, cmd_adr, 1);- spin_lock(chip->mutex); if (++z > 20) { /* Argh. Not ready for write to buffer */@@ -1520,44 +1513,68 @@ map_write(map, CMD(0x50), cmd_adr); map_write(map, CMD(0x70), cmd_adr); xip_enable(map, chip, cmd_adr);- printk(KERN_ERR "Chip not ready for buffer write. status = %lx, Xstatus = %lx\n",- status.x[0], Xstatus.x[0]);+ printk(KERN_ERR "%s: Chip not ready for buffer write. status = %lx, Xstatus = %lx\n",+ map->name, status.x[0], Xstatus.x[0]); ret = -EIO; goto out; } } + /* Figure out the number of words to write */+ word_gap = (-adr & (map_bankwidth(map)-1));+ words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map);+ if (!word_gap) {+ words--;+ } else {+ word_gap = map_bankwidth(map) - word_gap;+ adr -= word_gap;+ datum = map_word_ff(map);+ }+ /* Write length of data to come */- bytes = len & (map_bankwidth(map)-1);- words = len / map_bankwidth(map);- map_write(map, CMD(words - !bytes), cmd_adr );+ map_write(map, CMD(words), cmd_adr ); /* Write data */- z = 0;- while(z < words * map_bankwidth(map)) {- map_word datum = map_word_load(map, buf);- map_write(map, datum, adr+z);+ vec = *pvec;+ vec_seek = *pvec_seek;+ do {+ int n = map_bankwidth(map) - word_gap;+ if (n > vec->iov_len - vec_seek)+ n = vec->iov_len - vec_seek;+ if (n > len)+ n = len; - z += map_bankwidth(map);- buf += map_bankwidth(map);- }+ if (!word_gap && len < map_bankwidth(map))+ datum = map_word_ff(map);+ + datum = map_word_load_partial(map, datum,+ vec->iov_base + vec_seek, + word_gap, n); - if (bytes) {- map_word datum;+ len -= n;+ word_gap += n;+ if (!len || word_gap == map_bankwidth(map)) {+ map_write(map, datum, adr);+ adr += map_bankwidth(map);+ word_gap = 0;+ } - datum = map_word_ff(map);- datum = map_word_load_partial(map, datum, buf, 0, bytes);- map_write(map, datum, adr+z);- }+ vec_seek += n;+ if (vec_seek == vec->iov_len) {+ vec++;+ vec_seek = 0;+ }+ } while (len);+ *pvec = vec;+ *pvec_seek = vec_seek; /* GO GO GO */ map_write(map, CMD(0xd0), cmd_adr); chip->state = FL_WRITING; - spin_unlock(chip->mutex);- INVALIDATE_CACHED_RANGE(map, adr, len);- UDELAY(map, chip, cmd_adr, chip->buffer_write_time);- spin_lock(chip->mutex);+ INVALIDATE_CACHE_UDELAY(map, chip, + cmd_adr, len,+ chip->buffer_write_time); timeo = jiffies + (HZ/2); z = 0;@@ -1581,23 +1598,22 @@ /* OK Still waiting */ if (time_after(jiffies, timeo)) {+ map_write(map, CMD(0x70), cmd_adr); chip->state = FL_STATUS; xip_enable(map, chip, cmd_adr);- printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n");+ printk(KERN_ERR "%s: buffer write error (status timeout)\n", map->name); ret = -EIO; goto out; } /* Latency issues. Drop the lock, wait a while and retry */- spin_unlock(chip->mutex);- UDELAY(map, chip, cmd_adr, 1); z++;- spin_lock(chip->mutex);+ UDELAY(map, chip, cmd_adr, 1); } if (!z) { chip->buffer_write_time--; if (!chip->buffer_write_time)- chip->buffer_write_time++;+ chip->buffer_write_time = 1; } if (z > 1) chip->buffer_write_time++;@@ -1605,13 +1621,26 @@ /* Done and happy. */ chip->state = FL_STATUS; - /* check for lock bit */- if (map_word_bitsset(map, status, CMD(0x02))) {- /* clear status */+ /* check for errors */+ if (map_word_bitsset(map, status, CMD(0x1a))) {+ unsigned long chipstatus = MERGESTATUS(status);++ /* reset status */ map_write(map, CMD(0x50), cmd_adr);- /* put back into read status register mode */- map_write(map, CMD(0x70), adr);- ret = -EROFS;+ map_write(map, CMD(0x70), cmd_adr);+ xip_enable(map, chip, cmd_adr);++ if (chipstatus & 0x02) {+ ret = -EROFS;+ } else if (chipstatus & 0x08) {+ printk(KERN_ERR "%s: buffer write error (bad VPP)\n", map->name);+ ret = -EIO;+ } else {+ printk(KERN_ERR "%s: buffer write error (status 0x%lx)\n", map->name, chipstatus);+ ret = -EINVAL;+ }++ goto out; } xip_enable(map, chip, cmd_adr);@@ -1620,57 +1649,40 @@ return ret; } -static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to, - size_t len, size_t *retlen, const u_char *buf)+static int cfi_intelext_writev (struct mtd_info *mtd, const struct kvec *vecs,+ unsigned long count, loff_t to, size_t *retlen) { struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; int ret = 0; int chipnum;- unsigned long ofs;+ unsigned long ofs, vec_seek, i;+ size_t len = 0;++ for (i = 0; i < count; i++)+ len += vecs[i].iov_len; *retlen = 0; if (!len) return 0; chipnum = to >> cfi->chipshift;- ofs = to - (chipnum << cfi->chipshift);-- /* If it's not bus-aligned, do the first word write */- if (ofs & (map_bankwidth(map)-1)) {- size_t local_len = (-ofs)&(map_bankwidth(map)-1);- if (local_len > len)- local_len = len;- ret = cfi_intelext_write_words(mtd, to, local_len,- retlen, buf);- if (ret)- return ret;- ofs += local_len;- buf += local_len;- len -= local_len;+ ofs = to - (chipnum << cfi->chipshift);+ vec_seek = 0; - if (ofs >> cfi->chipshift) {- chipnum ++;- ofs = 0;- if (chipnum == cfi->numchips)- return 0;- }- }-- while(len) {+ do { /* We must not cross write block boundaries */ int size = wbufsize - (ofs & (wbufsize-1)); if (size > len) size = len; ret = do_write_buffer(map, &cfi->chips[chipnum], - ofs, buf, size);+ ofs, &vecs, &vec_seek, size); if (ret) return ret; ofs += size;- buf += size; (*retlen) += size; len -= size; @@ -1680,10 +1692,22 @@ if (chipnum == cfi->numchips) return 0; }- }+ } while (len);+ return 0; } +static int cfi_intelext_write_buffers (struct mtd_info *mtd, loff_t to,+ size_t len, size_t *retlen, const u_char *buf)+{+ struct kvec vec;++ vec.iov_base = (void *) buf;+ vec.iov_len = len;++ return cfi_intelext_writev(mtd, &vec, 1, to, retlen);+}+ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk) {@@ -1720,10 +1744,9 @@ chip->state = FL_ERASING; chip->erase_suspended = 0; - spin_unlock(chip->mutex);- INVALIDATE_CACHED_RANGE(map, adr, len);- UDELAY(map, chip, adr, chip->erase_time*1000/2);- spin_lock(chip->mutex);+ INVALIDATE_CACHE_UDELAY(map, chip,+ adr, len,+ chip->erase_time*1000/2); /* FIXME. Use a timer to check this, and return immediately. */ /* Once the state machine's known to be working I'll do that */@@ -1753,24 +1776,16 @@ /* OK Still waiting */ if (time_after(jiffies, timeo)) {- map_word Xstatus; map_write(map, CMD(0x70), adr); chip->state = FL_STATUS;- Xstatus = map_read(map, adr);- /* Clear status bits */- map_write(map, CMD(0x50), adr);- map_write(map, CMD(0x70), adr); xip_enable(map, chip, adr);- printk(KERN_ERR "waiting for erase at %08lx to complete timed out. status = %lx, Xstatus = %lx.\n",- adr, status.x[0], Xstatus.x[0]);+ printk(KERN_ERR "%s: block erase error: (status timeout)\n", map->name); ret = -EIO; goto out; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -