]> pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge git://git.infradead.org/mtd-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 7 Feb 2008 18:20:31 +0000 (10:20 -0800)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 7 Feb 2008 18:20:31 +0000 (10:20 -0800)
* git://git.infradead.org/mtd-2.6: (120 commits)
  [MTD] Fix mtdoops.c compilation
  [MTD] [NOR] fix startup lock when using multiple nor flash chips
  [MTD] [DOC200x] eccbuf is statically defined and always evaluate to true
  [MTD] Fix maps/physmap.c compilation with CONFIG_PM
  [MTD] onenand: Add panic_write function to the onenand driver
  [MTD] mtdoops: Use the panic_write function when present
  [MTD] Add mtd panic_write function pointer
  [MTD] [NAND] Freescale enhanced Local Bus Controller FCM NAND support.
  [MTD] physmap.c: Add support for multiple resources
  [MTD] [NAND] Fix misparenthesization introduced by commit 78b65179...
  [MTD] [NAND] Fix Blackfin NFC ECC calculating bug with page size 512 bytes
  [MTD] [NAND] Remove wrong operation in PM function of the BF54x NFC driver
  [MTD] [NAND] Remove unused variable in plat_nand_remove
  [MTD] Unlocking all Intel flash that is locked on power up.
  [MTD] [NAND] at91_nand: Make mtdparts option can override board info
  [MTD] mtdoops: Various minor cleanups
  [MTD] mtdoops: Ensure sequential write to the buffer
  [MTD] mtdoops: Perform write operations in a workqueue
  [MTD] mtdoops: Add further error return code checking
  [MTD] [NOR] Test devtype, not definition in flash_probe(), drivers/mtd/devices/lart.c
  ...

1  2 
drivers/mtd/devices/doc2000.c
drivers/mtd/nand/bf5xx_nand.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/s3c2410.c
fs/jffs2/fs.c
fs/jffs2/readinode.c
fs/jffs2/write.c

index 90acf57c19bd29962197cf9ed83fa332e3888a4c,e9ce241b7fe5be65b2e505715ff0bd138ba1a4a4..846989f292e3f01a1992dd73f999583263b9ec7f
@@@ -376,7 -376,7 +376,7 @@@ static int DoC_IdentChip(struct DiskOnC
         * hardware restriction. */
        if (doc->mfr) {
                if (doc->mfr == mfr && doc->id == id)
 -                      return 1;       /* This is another the same the first */
 +                      return 1;       /* This is the same as the first */
                else
                        printk(KERN_WARNING
                               "Flash chip at floor %d, chip %d is different:\n",
@@@ -632,7 -632,7 +632,7 @@@ static int doc_read(struct mtd_info *mt
                        len = ((from | 0x1ff) + 1) - from;
  
                /* The ECC will not be calculated correctly if less than 512 is read */
-               if (len != 0x200 && eccbuf)
+               if (len != 0x200)
                        printk(KERN_WARNING
                               "ECC needs a full sector read (adr: %lx size %lx)\n",
                               (long) from, (long) len);
@@@ -896,7 -896,7 +896,7 @@@ static int doc_write(struct mtd_info *m
                /* Let the caller know we completed it */
                *retlen += len;
  
-               if (eccbuf) {
+               {
                        unsigned char x[8];
                        size_t dummy;
                        int ret;
index a52f3a737c39a606e0832b3db47f19effa274a83,7d6ac6a7d9a7c3409ccec3ccc9c6f956b3d8aeec..747042ab094a6b101e558a4f379ff9b2848a81c1
@@@ -4,7 -4,7 +4,7 @@@
   *    http://blackfin.uclinux.org/
   *    Bryan Wu <bryan.wu@analog.com>
   *
 - * Blackfin BF5xx on-chip NAND flash controler driver
 + * Blackfin BF5xx on-chip NAND flash controller driver
   *
   * Derived from drivers/mtd/nand/s3c2410.c
   * Copyright (c) 2007 Ben Dooks <ben@simtec.co.uk>
@@@ -74,7 -74,22 +74,22 @@@ static int hardware_ecc = 1
  static int hardware_ecc;
  #endif
  
- static unsigned short bfin_nfc_pin_req[] = {P_NAND_CE, P_NAND_RB, 0};
+ static unsigned short bfin_nfc_pin_req[] =
+       {P_NAND_CE,
+        P_NAND_RB,
+        P_NAND_D0,
+        P_NAND_D1,
+        P_NAND_D2,
+        P_NAND_D3,
+        P_NAND_D4,
+        P_NAND_D5,
+        P_NAND_D6,
+        P_NAND_D7,
+        P_NAND_WE,
+        P_NAND_RE,
+        P_NAND_CLE,
+        P_NAND_ALE,
+        0};
  
  /*
   * Data structures for bf5xx nand flash controller driver
@@@ -278,7 -293,6 +293,6 @@@ static int bf5xx_nand_calculate_ecc(str
        u16 ecc0, ecc1;
        u32 code[2];
        u8 *p;
-       int bytes = 3, i;
  
        /* first 4 bytes ECC code for 256 page size */
        ecc0 = bfin_read_NFC_ECC0();
  
        dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
  
+       /* first 3 bytes in ecc_code for 256 page size */
+       p = (u8 *) code;
+       memcpy(ecc_code, p, 3);
        /* second 4 bytes ECC code for 512 page size */
        if (page_size == 512) {
                ecc0 = bfin_read_NFC_ECC2();
                ecc1 = bfin_read_NFC_ECC3();
                code[1] = (ecc0 & 0x3FF) | ((ecc1 & 0x3FF) << 11);
-               bytes = 6;
+               /* second 3 bytes in ecc_code for second 256
+                * bytes of 512 page size
+                */
+               p = (u8 *) (code + 1);
+               memcpy((ecc_code + 3), p, 3);
                dev_dbg(info->device, "returning ecc 0x%08x\n", code[1]);
        }
  
-       p = (u8 *)code;
-       for (i = 0; i < bytes; i++)
-               ecc_code[i] = p[i];
        return 0;
  }
  
@@@ -507,12 -526,13 +526,13 @@@ static int bf5xx_nand_dma_init(struct b
  
        init_completion(&info->dma_completion);
  
+ #ifdef CONFIG_BF54x
        /* Setup DMAC1 channel mux for NFC which shared with SDH */
        val = bfin_read_DMAC1_PERIMUX();
        val &= 0xFFFE;
        bfin_write_DMAC1_PERIMUX(val);
        SSYNC();
+ #endif
        /* Request NFC DMA channel */
        ret = request_dma(CH_NFC, "BF5XX NFC driver");
        if (ret < 0) {
@@@ -744,9 -764,6 +764,6 @@@ static int bf5xx_nand_resume(struct pla
  {
        struct bf5xx_nand_info *info = platform_get_drvdata(dev);
  
-       if (info)
-               bf5xx_nand_hw_init(info);
        return 0;
  }
  
index ddd4fc019042ff72250c887944a3410ec6b69459,971d58c391f1c90b07b21285f3b18d643a531d64..7acb1a0e7409fbf950a06e97f8e58b3a1be38559
@@@ -89,7 -89,7 +89,7 @@@ static int nand_do_write_oob(struct mtd
                             struct mtd_oob_ops *ops);
  
  /*
 - * For devices which display every fart in the system on a seperate LED. Is
 + * For devices which display every fart in the system on a separate LED. Is
   * compiled away when LED support is disabled.
   */
  DEFINE_LED_TRIGGER(nand_led_trigger);
@@@ -2469,8 -2469,12 +2469,12 @@@ int nand_scan_tail(struct mtd_info *mtd
                        chip->ecc.write_oob = nand_write_oob_std;
  
        case NAND_ECC_HW_SYNDROME:
-               if (!chip->ecc.calculate || !chip->ecc.correct ||
-                   !chip->ecc.hwctl) {
+               if ((!chip->ecc.calculate || !chip->ecc.correct ||
+                    !chip->ecc.hwctl) &&
+                   (!chip->ecc.read_page ||
+                    chip->ecc.read_page == nand_read_page_hwecc ||
+                    !chip->ecc.write_page ||
+                    chip->ecc.write_page == nand_write_page_hwecc)) {
                        printk(KERN_WARNING "No ECC functions supplied, "
                               "Hardware ECC not possible\n");
                        BUG();
index 2bd0737572c6fe9146a5b26d6f4147a2e76daea8,d31cb7b3feeb75b6f0376422f1c53a2d3c696d98..9260ad947524f4f4a28959a3b843f48a8069c7f8
@@@ -8,7 -8,7 +8,7 @@@
   *
   * Changelog:
   *    21-Sep-2004  BJD  Initial version
 - *    23-Sep-2004  BJD  Mulitple device support
 + *    23-Sep-2004  BJD  Multiple device support
   *    28-Sep-2004  BJD  Fixed ECC placement for Hardware mode
   *    12-Oct-2004  BJD  Fixed errors in use of platform data
   *    18-Feb-2005  BJD  Fix sparse errors
@@@ -120,6 -120,8 +120,8 @@@ struct s3c2410_nand_info 
        int                             sel_bit;
        int                             mtd_count;
  
+       unsigned long                   save_nfconf;
        enum s3c_cpu_type               cpu_type;
  };
  
@@@ -364,23 -366,21 +366,21 @@@ static int s3c2410_nand_correct_data(st
            ((diff2 ^ (diff2 >> 1)) & 0x55) == 0x55) {
                /* calculate the bit position of the error */
  
-               bit  = (diff2 >> 2) & 1;
-               bit |= (diff2 >> 3) & 2;
-               bit |= (diff2 >> 4) & 4;
+               bit  = ((diff2 >> 3) & 1) |
+                      ((diff2 >> 4) & 2) |
+                      ((diff2 >> 5) & 4);
  
                /* calculate the byte position of the error */
  
-               byte  = (diff1 << 1) & 0x80;
-               byte |= (diff1 << 2) & 0x40;
-               byte |= (diff1 << 3) & 0x20;
-               byte |= (diff1 << 4) & 0x10;
-               byte |= (diff0 >> 3) & 0x08;
-               byte |= (diff0 >> 2) & 0x04;
-               byte |= (diff0 >> 1) & 0x02;
-               byte |= (diff0 >> 0) & 0x01;
-               byte |= (diff2 << 8) & 0x100;
+               byte = ((diff2 << 7) & 0x100) |
+                      ((diff1 << 0) & 0x80)  |
+                      ((diff1 << 1) & 0x40)  |
+                      ((diff1 << 2) & 0x20)  |
+                      ((diff1 << 3) & 0x10)  |
+                      ((diff0 >> 4) & 0x08)  |
+                      ((diff0 >> 3) & 0x04)  |
+                      ((diff0 >> 2) & 0x02)  |
+                      ((diff0 >> 1) & 0x01);
  
                dev_dbg(info->device, "correcting error bit %d, byte %d\n",
                        bit, byte);
        if ((diff0 & ~(1<<fls(diff0))) == 0)
                return 1;
  
-       return 0;
+       return -1;
  }
  
  /* ECC functions
@@@ -810,6 -810,16 +810,16 @@@ static int s3c24xx_nand_suspend(struct 
        struct s3c2410_nand_info *info = platform_get_drvdata(dev);
  
        if (info) {
+               info->save_nfconf = readl(info->regs + S3C2410_NFCONF);
+               /* For the moment, we must ensure nFCE is high during
+                * the time we are suspended. This really should be
+                * handled by suspending the MTDs we are using, but
+                * that is currently not the case. */
+               writel(info->save_nfconf | info->sel_bit,
+                      info->regs + S3C2410_NFCONF);
                if (!allow_clk_stop(info))
                        clk_disable(info->clk);
        }
  static int s3c24xx_nand_resume(struct platform_device *dev)
  {
        struct s3c2410_nand_info *info = platform_get_drvdata(dev);
+       unsigned long nfconf;
  
        if (info) {
                clk_enable(info->clk);
                s3c2410_nand_inithw(info, dev);
  
+               /* Restore the state of the nFCE line. */
+               nfconf = readl(info->regs + S3C2410_NFCONF);
+               nfconf &= ~info->sel_bit;
+               nfconf |= info->save_nfconf & info->sel_bit;
+               writel(nfconf, info->regs + S3C2410_NFCONF);
                if (allow_clk_stop(info))
                        clk_disable(info->clk);
        }
diff --combined fs/jffs2/fs.c
index 6d1eaddde0ecd70426eb5f760f9e6f1460ad7826,ee192af0b8b00a5bdffc766d12dfa66ae8739f6e..e26ea78c7892f7a4f157819a06e052add03057fd
@@@ -97,11 -97,7 +97,7 @@@ int jffs2_do_setattr (struct inode *ino
        ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid);
  
        if (ivalid & ATTR_MODE)
-               if (iattr->ia_mode & S_ISGID &&
-                   !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID))
-                       ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID);
-               else
-                       ri->mode = cpu_to_jemode(iattr->ia_mode);
+               ri->mode = cpu_to_jemode(iattr->ia_mode);
        else
                ri->mode = cpu_to_jemode(inode->i_mode);
  
@@@ -230,23 -226,16 +226,23 @@@ void jffs2_clear_inode (struct inode *i
        jffs2_do_clear_inode(c, f);
  }
  
 -void jffs2_read_inode (struct inode *inode)
 +struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
  {
        struct jffs2_inode_info *f;
        struct jffs2_sb_info *c;
        struct jffs2_raw_inode latest_node;
        union jffs2_device_node jdev;
 +      struct inode *inode;
        dev_t rdev = 0;
        int ret;
  
 -      D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino));
 +      D1(printk(KERN_DEBUG "jffs2_iget(): ino == %lu\n", ino));
 +
 +      inode = iget_locked(sb, ino);
 +      if (!inode)
 +              return ERR_PTR(-ENOMEM);
 +      if (!(inode->i_state & I_NEW))
 +              return inode;
  
        f = JFFS2_INODE_INFO(inode);
        c = JFFS2_SB_INFO(inode->i_sb);
        ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
  
        if (ret) {
 -              make_bad_inode(inode);
                up(&f->sem);
 -              return;
 +              iget_failed(inode);
 +              return ERR_PTR(ret);
        }
        inode->i_mode = jemode_to_cpu(latest_node.mode);
        inode->i_uid = je16_to_cpu(latest_node.uid);
                if (f->metadata->size != sizeof(jdev.old) &&
                    f->metadata->size != sizeof(jdev.new)) {
                        printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size);
 -                      up(&f->sem);
 -                      jffs2_do_clear_inode(c, f);
 -                      make_bad_inode(inode);
 -                      return;
 +                      goto error_io;
                }
                D1(printk(KERN_DEBUG "Reading device numbers from flash\n"));
 -              if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) {
 +              ret = jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size);
 +              if (ret < 0) {
                        /* Eep */
                        printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
 -                      up(&f->sem);
 -                      jffs2_do_clear_inode(c, f);
 -                      make_bad_inode(inode);
 -                      return;
 +                      goto error;
                }
                if (f->metadata->size == sizeof(jdev.old))
                        rdev = old_decode_dev(je16_to_cpu(jdev.old));
        up(&f->sem);
  
        D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n"));
 +      unlock_new_inode(inode);
 +      return inode;
 +
 +error_io:
 +      ret = -EIO;
 +error:
 +      up(&f->sem);
 +      jffs2_do_clear_inode(c, f);
 +      iget_failed(inode);
 +      return ERR_PTR(ret);
  }
  
  void jffs2_dirty_inode(struct inode *inode)
@@@ -534,16 -518,15 +530,16 @@@ int jffs2_do_fill_super(struct super_bl
        if ((ret = jffs2_do_mount_fs(c)))
                goto out_inohash;
  
 -      ret = -EINVAL;
 -
        D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n"));
 -      root_i = iget(sb, 1);
 -      if (is_bad_inode(root_i)) {
 +      root_i = jffs2_iget(sb, 1);
 +      if (IS_ERR(root_i)) {
                D1(printk(KERN_WARNING "get root inode failed\n"));
 -              goto out_root_i;
 +              ret = PTR_ERR(root_i);
 +              goto out_root;
        }
  
 +      ret = -ENOMEM;
 +
        D1(printk(KERN_DEBUG "jffs2_do_fill_super(): d_alloc_root()\n"));
        sb->s_root = d_alloc_root(root_i);
        if (!sb->s_root)
  
   out_root_i:
        iput(root_i);
 +out_root:
        jffs2_free_ino_caches(c);
        jffs2_free_raw_node_refs(c);
        if (jffs2_blocks_use_vmalloc(c))
@@@ -629,9 -611,9 +625,9 @@@ struct jffs2_inode_info *jffs2_gc_fetch
                   jffs2_do_unlink() would need the alloc_sem and we have it.
                   Just iget() it, and if read_inode() is necessary that's OK.
                */
 -              inode = iget(OFNI_BS_2SFFJ(c), inum);
 -              if (!inode)
 -                      return ERR_PTR(-ENOMEM);
 +              inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
 +              if (IS_ERR(inode))
 +                      return ERR_CAST(inode);
        }
        if (is_bad_inode(inode)) {
                printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u. nlink %d\n",
diff --combined fs/jffs2/readinode.c
index 6c1ba3566f58b4c498c1cfa7a3a627db9e089eeb,fb89ab5e1d500faffc7bba2971a542de4c04dbc0..e512a93d624954e04b70ab0a27bf85eb43a61fea
@@@ -37,23 -37,24 +37,24 @@@ static int check_node_data(struct jffs2
  
        BUG_ON(tn->csize == 0);
  
-       if (!jffs2_is_writebuffered(c))
-               goto adj_acc;
        /* Calculate how many bytes were already checked */
        ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode);
-       len = ofs % c->wbuf_pagesize;
-       if (likely(len))
-               len = c->wbuf_pagesize - len;
+       len = tn->csize;
  
-       if (len >= tn->csize) {
-               dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n",
-                       ref_offset(ref), tn->csize, ofs);
-               goto adj_acc;
-       }
+       if (jffs2_is_writebuffered(c)) {
+               int adj = ofs % c->wbuf_pagesize;
+               if (likely(adj))
+                       adj = c->wbuf_pagesize - adj;
  
-       ofs += len;
-       len = tn->csize - len;
+               if (adj >= tn->csize) {
+                       dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n",
+                                     ref_offset(ref), tn->csize, ofs);
+                       goto adj_acc;
+               }
+               ofs += adj;
+               len -= adj;
+       }
  
        dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n",
                ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len);
@@@ -63,7 -64,7 +64,7 @@@
         * adding and jffs2_flash_read_end() interface. */
        if (c->mtd->point) {
                err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer);
-               if (!err && retlen < tn->csize) {
+               if (!err && retlen < len) {
                        JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize);
                        c->mtd->unpoint(c->mtd, buffer, ofs, retlen);
                } else if (err)
@@@ -741,7 -742,7 +742,7 @@@ static inline int read_dnode(struct jff
                         * are not obsolete.
                         *
                         * Of course, this optimization only makes sense in case
 -                       * of NAND flashes (or other flashes whith
 +                       * of NAND flashes (or other flashes with
                         * !jffs2_can_mark_obsolete()), since on NOR flashes
                         * nodes are marked obsolete physically.
                         *
diff --combined fs/jffs2/write.c
index 1b88e6e734efa17e9c0c4e517b984bf3759640c4,ecdf18d0486fcac316a5f90be375d2cd92519421..776f13cbf2b5e62fef50abfee752e71f93b5e0ee
@@@ -177,7 -177,7 +177,7 @@@ struct jffs2_full_dnode *jffs2_write_dn
                void *hold_err = fn->raw;
                /* Release the full_dnode which is now useless, and return */
                jffs2_free_full_dnode(fn);
 -              return ERR_PTR(PTR_ERR(hold_err));
 +              return ERR_CAST(hold_err);
        }
        fn->ofs = je32_to_cpu(ri->offset);
        fn->size = je32_to_cpu(ri->dsize);
@@@ -313,7 -313,7 +313,7 @@@ struct jffs2_full_dirent *jffs2_write_d
                void *hold_err = fd->raw;
                /* Release the full_dirent which is now useless, and return */
                jffs2_free_full_dirent(fd);
 -              return ERR_PTR(PTR_ERR(hold_err));
 +              return ERR_CAST(hold_err);
        }
  
        if (retried) {
@@@ -582,7 -582,7 +582,7 @@@ int jffs2_do_unlink(struct jffs2_sb_inf
                jffs2_add_fd_to_list(c, fd, &dir_f->dents);
                up(&dir_f->sem);
        } else {
-               struct jffs2_full_dirent **prev = &dir_f->dents;
+               struct jffs2_full_dirent *fd = dir_f->dents;
                uint32_t nhash = full_name_hash(name, namelen);
  
                /* We don't actually want to reserve any space, but we do
                down(&c->alloc_sem);
                down(&dir_f->sem);
  
-               while ((*prev) && (*prev)->nhash <= nhash) {
-                       if ((*prev)->nhash == nhash &&
-                           !memcmp((*prev)->name, name, namelen) &&
-                           !(*prev)->name[namelen]) {
-                               struct jffs2_full_dirent *this = *prev;
+               for (fd = dir_f->dents; fd; fd = fd->next) {
+                       if (fd->nhash == nhash &&
+                           !memcmp(fd->name, name, namelen) &&
+                           !fd->name[namelen]) {
  
                                D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n",
-                                         this->ino, ref_offset(this->raw)));
-                               *prev = this->next;
-                               jffs2_mark_node_obsolete(c, (this->raw));
-                               jffs2_free_full_dirent(this);
+                                         fd->ino, ref_offset(fd->raw)));
+                               jffs2_mark_node_obsolete(c, fd->raw);
+                               /* We don't want to remove it from the list immediately,
+                                  because that screws up getdents()/seek() semantics even
+                                  more than they're screwed already. Turn it into a
+                                  node-less deletion dirent instead -- a placeholder */
+                               fd->raw = NULL;
+                               fd->ino = 0;
                                break;
                        }
-                       prev = &((*prev)->next);
                }
                up(&dir_f->sem);
        }
                                        D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n",
                                                fd->name, dead_f->inocache->ino));
                                }
-                               jffs2_mark_node_obsolete(c, fd->raw);
+                               if (fd->raw)
+                                       jffs2_mark_node_obsolete(c, fd->raw);
                                jffs2_free_full_dirent(fd);
                        }
                }