Merge git://git.infradead.org/mtd-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 30 Oct 2010 15:31:35 +0000 (08:31 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 30 Oct 2010 15:31:35 +0000 (08:31 -0700)
* git://git.infradead.org/mtd-2.6: (82 commits)
  mtd: fix build error in m25p80.c
  mtd: Remove redundant mutex from mtd_blkdevs.c
  MTD: Fix wrong check register_blkdev return value
  Revert "mtd: cleanup Kconfig dependencies"
  mtd: cfi_cmdset_0002: make sector erase command variable
  mtd: cfi_cmdset_0002: add CFI detection for SST 38VF640x chips
  mtd: cfi_util: add support for switching SST 39VF640xB chips into QRY mode
  mtd: cfi_cmdset_0001: use defined value of P_ID_INTEL_PERFORMANCE instead of hardcoded one
  block2mtd: dubious assignment
  P4080/mtd: Fix the freescale lbc issue with 36bit mode
  P4080/eLBC: Make Freescale elbc interrupt common to elbc devices
  mtd: phram: use KBUILD_MODNAME
  mtd: OneNAND: S5PC110: Fix double call suspend & resume function
  mtd: nand: fix MTD_MODE_RAW writes
  jffs2: use kmemdup
  mtd: sm_ftl: cosmetic, use bool when possible
  mtd: r852: remove useless pci powerup/down from suspend/resume routines
  mtd: blktrans: fix a race vs kthread_stop
  mtd: blktrans: kill BKL
  mtd: allow to unload the mtdtrans module if its block devices aren't open
  ...

Fix up trivial whitespace-introduced conflict in drivers/mtd/mtdchar.c

1  2 
arch/powerpc/Kconfig
drivers/mtd/mtdchar.c
drivers/mtd/nand/davinci_nand.c
fs/jffs2/dir.c

diff --combined arch/powerpc/Kconfig
@@@ -1,3 -1,9 +1,3 @@@
 -# For a description of the syntax of this configuration file,
 -# see Documentation/kbuild/kconfig-language.txt.
 -#
 -
 -mainmenu "Linux/PowerPC Kernel Configuration"
 -
  source "arch/powerpc/platforms/Kconfig.cputype"
  
  config PPC32
@@@ -682,9 -688,12 +682,12 @@@ config 4xx_SO
        bool
  
  config FSL_LBC
-       bool
+       bool "Freescale Local Bus support"
+       depends on FSL_SOC
        help
-         Freescale Localbus support
+         Enables reporting of errors from the Freescale local bus
+         controller.  Also contains some common code used by
+         drivers for specific local bus peripherals.
  
  config FSL_GTM
        bool
diff --combined drivers/mtd/mtdchar.c
@@@ -30,8 -30,9 +30,9 @@@
  #include <linux/backing-dev.h>
  #include <linux/compat.h>
  #include <linux/mount.h>
+ #include <linux/blkpg.h>
  #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
  #include <linux/mtd/map.h>
  
  #include <asm/uaccess.h>
@@@ -478,6 -479,78 +479,78 @@@ static int mtd_do_readoob(struct mtd_in
        return ret;
  }
  
+ /*
+  * Copies (and truncates, if necessary) data from the larger struct,
+  * nand_ecclayout, to the smaller, deprecated layout struct,
+  * nand_ecclayout_user. This is necessary only to suppport the deprecated
+  * API ioctl ECCGETLAYOUT while allowing all new functionality to use
+  * nand_ecclayout flexibly (i.e. the struct may change size in new
+  * releases without requiring major rewrites).
+  */
+ static int shrink_ecclayout(const struct nand_ecclayout *from,
+               struct nand_ecclayout_user *to)
+ {
+       int i;
+       if (!from || !to)
+               return -EINVAL;
+       memset(to, 0, sizeof(*to));
+       to->eccbytes = min((int)from->eccbytes, MTD_MAX_ECCPOS_ENTRIES);
+       for (i = 0; i < to->eccbytes; i++)
+               to->eccpos[i] = from->eccpos[i];
+       for (i = 0; i < MTD_MAX_OOBFREE_ENTRIES; i++) {
+               if (from->oobfree[i].length == 0 &&
+                               from->oobfree[i].offset == 0)
+                       break;
+               to->oobavail += from->oobfree[i].length;
+               to->oobfree[i] = from->oobfree[i];
+       }
+       return 0;
+ }
+ #ifdef CONFIG_MTD_PARTITIONS
+ static int mtd_blkpg_ioctl(struct mtd_info *mtd,
+                          struct blkpg_ioctl_arg __user *arg)
+ {
+       struct blkpg_ioctl_arg a;
+       struct blkpg_partition p;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       /* Only master mtd device must be used to control partitions */
+       if (!mtd_is_master(mtd))
+               return -EINVAL;
+       if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
+               return -EFAULT;
+       if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
+               return -EFAULT;
+       switch (a.op) {
+       case BLKPG_ADD_PARTITION:
+               return mtd_add_partition(mtd, p.devname, p.start, p.length);
+       case BLKPG_DEL_PARTITION:
+               if (p.pno < 0)
+                       return -EINVAL;
+               return mtd_del_partition(mtd, p.pno);
+       default:
+               return -EINVAL;
+       }
+ }
+ #endif
  static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
  {
        struct mtd_file_info *mfi = file->private_data;
                if (get_user(ur_idx, &(ur->regionindex)))
                        return -EFAULT;
  
+               if (ur_idx >= mtd->numeraseregions)
+                       return -EINVAL;
                kr = &(mtd->eraseregions[ur_idx]);
  
                if (put_user(kr->offset, &(ur->offset))
        }
  #endif
  
+       /* This ioctl is being deprecated - it truncates the ecc layout */
        case ECCGETLAYOUT:
        {
+               struct nand_ecclayout_user *usrlay;
                if (!mtd->ecclayout)
                        return -EOPNOTSUPP;
  
-               if (copy_to_user(argp, mtd->ecclayout,
-                                sizeof(struct nand_ecclayout)))
-                       return -EFAULT;
+               usrlay = kmalloc(sizeof(*usrlay), GFP_KERNEL);
+               if (!usrlay)
+                       return -ENOMEM;
+               shrink_ecclayout(mtd->ecclayout, usrlay);
+               if (copy_to_user(argp, usrlay, sizeof(*usrlay)))
+                       ret = -EFAULT;
+               kfree(usrlay);
                break;
        }
  
                break;
        }
  
+ #ifdef CONFIG_MTD_PARTITIONS
+       case BLKPG:
+       {
+               ret = mtd_blkpg_ioctl(mtd,
+                     (struct blkpg_ioctl_arg __user *)arg);
+               break;
+       }
+       case BLKRRPART:
+       {
+               /* No reread partition feature. Just return ok */
+               ret = 0;
+               break;
+       }
+ #endif
        default:
                ret = -ENOTTY;
        }
@@@ -1030,15 -1131,17 +1131,15 @@@ static const struct file_operations mtd
  #endif
  };
  
 -static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags,
 -                               const char *dev_name, void *data,
 -                               struct vfsmount *mnt)
 +static struct dentry *mtd_inodefs_mount(struct file_system_type *fs_type,
 +                              int flags, const char *dev_name, void *data)
  {
-         return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC);
 -      return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC,
 -                             mnt);
++      return mount_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC);
  }
  
  static struct file_system_type mtd_inodefs_type = {
         .name = "mtd_inodefs",
 -       .get_sb = mtd_inodefs_get_sb,
 +       .mount = mtd_inodefs_mount,
         .kill_sb = kill_anon_super,
  };
  
@@@ -35,7 -35,6 +35,7 @@@
  #include <linux/slab.h>
  
  #include <mach/nand.h>
 +#include <mach/aemif.h>
  
  #include <asm/mach-types.h>
  
@@@ -75,8 -74,6 +75,8 @@@ struct davinci_nand_info 
        uint32_t                mask_cle;
  
        uint32_t                core_chipsel;
 +
 +      struct davinci_aemif_timing     *timing;
  };
  
  static DEFINE_SPINLOCK(davinci_nand_lock);
@@@ -316,7 -313,7 +316,7 @@@ static int nand_davinci_correct_4bit(st
        u32 syndrome[4];
        u32 ecc_state;
        unsigned num_errors, corrected;
-       unsigned long timeo = jiffies + msecs_to_jiffies(100);
+       unsigned long timeo;
  
        /* All bytes 0xff?  It's an erased page; ignore its ECC. */
        for (i = 0; i < 10; i++) {
@@@ -372,9 -369,11 +372,11 @@@ compare
         * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately
         * begin trying to poll for the state, you may fall right out of your
         * loop without any of the correction calculations having taken place.
-        * The recommendation from the hardware team is to wait till ECC_STATE
-        * reads less than 4, which means ECC HW has entered correction state.
+        * The recommendation from the hardware team is to initially delay as
+        * long as ECC_STATE reads less than 4. After that, ECC HW has entered
+        * correction state.
         */
+       timeo = jiffies + usecs_to_jiffies(100);
        do {
                ecc_state = (davinci_nand_readl(info,
                                NANDFSR_OFFSET) >> 8) & 0x0f;
@@@ -481,6 -480,36 +483,6 @@@ static int nand_davinci_dev_ready(struc
        return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
  }
  
 -static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
 -{
 -      uint32_t regval, a1cr;
 -
 -      /*
 -       * NAND FLASH timings @ PLL1 == 459 MHz
 -       *  - AEMIF.CLK freq   = PLL1/6 = 459/6 = 76.5 MHz
 -       *  - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns
 -       */
 -      regval = 0
 -              | (0 << 31)           /* selectStrobe */
 -              | (0 << 30)           /* extWait (never with NAND) */
 -              | (1 << 26)           /* writeSetup      10 ns */
 -              | (3 << 20)           /* writeStrobe     40 ns */
 -              | (1 << 17)           /* writeHold       10 ns */
 -              | (0 << 13)           /* readSetup       10 ns */
 -              | (3 << 7)            /* readStrobe      60 ns */
 -              | (0 << 4)            /* readHold        10 ns */
 -              | (3 << 2)            /* turnAround      ?? ns */
 -              | (0 << 0)            /* asyncSize       8-bit bus */
 -              ;
 -      a1cr = davinci_nand_readl(info, A1CR_OFFSET);
 -      if (a1cr != regval) {
 -              dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \
 -                     "reg to 0x%08x, was 0x%08x, should be done by " \
 -                     "bootloader.\n", regval, a1cr);
 -              davinci_nand_writel(info, A1CR_OFFSET, regval);
 -      }
 -}
 -
  /*----------------------------------------------------------------------*/
  
  /* An ECC layout for using 4-bit ECC with small-page flash, storing
@@@ -584,7 -613,6 +586,7 @@@ static int __init nand_davinci_probe(st
        info->chip.options      = pdata->options;
        info->chip.bbt_td       = pdata->bbt_td;
        info->chip.bbt_md       = pdata->bbt_md;
 +      info->timing            = pdata->timing;
  
        info->ioaddr            = (uint32_t __force) vaddr;
  
                goto err_clk_enable;
        }
  
 -      /* EMIF timings should normally be set by the boot loader,
 -       * especially after boot-from-NAND.  The *only* reason to
 -       * have this special casing for the DM6446 EVM is to work
 -       * with boot-from-NOR ... with CS0 manually re-jumpered
 -       * (after startup) so it addresses the NAND flash, not NOR.
 -       * Even for dev boards, that's unusually rude...
 +      /*
 +       * Setup Async configuration register in case we did not boot from
 +       * NAND and so bootloader did not bother to set it up.
         */
 -      if (machine_is_davinci_evm())
 -              nand_dm6446evm_flash_init(info);
 +      val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
 +
 +      /* Extended Wait is not valid and Select Strobe mode is not used */
 +      val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
 +      if (info->chip.options & NAND_BUSWIDTH_16)
 +              val |= 0x1;
 +
 +      davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
 +
 +      ret = davinci_aemif_setup_timing(info->timing, info->base,
 +                                                      info->core_chipsel);
 +      if (ret < 0) {
 +              dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
 +              goto err_timing;
 +      }
  
        spin_lock_irq(&davinci_nand_lock);
  
                 * breaks userspace ioctl interface with mtd-utils. Once we
                 * resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used
                 * for the 4KiB page chips.
+                *
+                * TODO: Note that nand_ecclayout has now been expanded and can
+                *  hold plenty of OOB entries.
                 */
                dev_warn(&pdev->dev, "no 4-bit ECC support yet "
                                "for 4KiB-page NAND\n");
@@@ -793,7 -814,6 +798,7 @@@ syndrome_done
        return 0;
  
  err_scan:
 +err_timing:
        clk_disable(info->clk);
  
  err_clk_enable:
diff --combined fs/jffs2/dir.c
@@@ -289,7 -289,7 +289,7 @@@ static int jffs2_link (struct dentry *o
                mutex_unlock(&f->sem);
                d_instantiate(dentry, old_dentry->d_inode);
                dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
 -              atomic_inc(&old_dentry->d_inode->i_count);
 +              ihold(old_dentry->d_inode);
        }
        return ret;
  }
@@@ -367,7 -367,7 +367,7 @@@ static int jffs2_symlink (struct inode 
        }
  
        /* We use f->target field to store the target path. */
-       f->target = kmalloc(targetlen + 1, GFP_KERNEL);
+       f->target = kmemdup(target, targetlen + 1, GFP_KERNEL);
        if (!f->target) {
                printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1);
                mutex_unlock(&f->sem);
                goto fail;
        }
  
-       memcpy(f->target, target, targetlen + 1);
        D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target));
  
        /* No data here. Only a metadata node, which will be
@@@ -864,7 -863,7 +863,7 @@@ static int jffs2_rename (struct inode *
                printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
                /* Might as well let the VFS know */
                d_instantiate(new_dentry, old_dentry->d_inode);
 -              atomic_inc(&old_dentry->d_inode->i_count);
 +              ihold(old_dentry->d_inode);
                new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
                return ret;
        }