Merge git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
authorDavid Woodhouse <dwmw2@infradead.org>
Sun, 3 Feb 2008 07:29:41 +0000 (18:29 +1100)
committerDavid Woodhouse <dwmw2@infradead.org>
Sun, 3 Feb 2008 07:30:32 +0000 (18:30 +1100)
1  2 
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/mtdchar.c

index 8189adfefaef5db6c26b81ae4b329d9fcee1ff16,1707f98c322c589c144b59d19cd9a52cbb22377a..47794d23a42ec2029371f35cf71bea6eafd8f073
@@@ -50,7 -50,6 +50,7 @@@
  #define I82802AC      0x00ac
  #define MANUFACTURER_ST         0x0020
  #define M50LPW080       0x002F
 +#define AT49BV640D    0x02de
  
  static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
  static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
@@@ -158,47 -157,6 +158,47 @@@ static void cfi_tell_features(struct cf
  }
  #endif
  
 +/* Atmel chips don't use the same PRI format as Intel chips */
 +static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
 +{
 +      struct map_info *map = mtd->priv;
 +      struct cfi_private *cfi = map->fldrv_priv;
 +      struct cfi_pri_intelext *extp = cfi->cmdset_priv;
 +      struct cfi_pri_atmel atmel_pri;
 +      uint32_t features = 0;
 +
 +      /* Reverse byteswapping */
 +      extp->FeatureSupport = cpu_to_le32(extp->FeatureSupport);
 +      extp->BlkStatusRegMask = cpu_to_le16(extp->BlkStatusRegMask);
 +      extp->ProtRegAddr = cpu_to_le16(extp->ProtRegAddr);
 +
 +      memcpy(&atmel_pri, extp, sizeof(atmel_pri));
 +      memset((char *)extp + 5, 0, sizeof(*extp) - 5);
 +
 +      printk(KERN_ERR "atmel Features: %02x\n", atmel_pri.Features);
 +
 +      if (atmel_pri.Features & 0x01) /* chip erase supported */
 +              features |= (1<<0);
 +      if (atmel_pri.Features & 0x02) /* erase suspend supported */
 +              features |= (1<<1);
 +      if (atmel_pri.Features & 0x04) /* program suspend supported */
 +              features |= (1<<2);
 +      if (atmel_pri.Features & 0x08) /* simultaneous operations supported */
 +              features |= (1<<9);
 +      if (atmel_pri.Features & 0x20) /* page mode read supported */
 +              features |= (1<<7);
 +      if (atmel_pri.Features & 0x40) /* queued erase supported */
 +              features |= (1<<4);
 +      if (atmel_pri.Features & 0x80) /* Protection bits supported */
 +              features |= (1<<6);
 +
 +      extp->FeatureSupport = features;
 +
 +      /* burst write mode not supported */
 +      cfi->cfiq->BufWriteTimeoutTyp = 0;
 +      cfi->cfiq->BufWriteTimeoutMax = 0;
 +}
 +
  #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
  /* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
  static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
@@@ -269,20 -227,13 +269,20 @@@ static void fixup_use_write_buffers(str
  /*
   * Some chips power-up with all sectors locked by default.
   */
 -static void fixup_use_powerup_lock(struct mtd_info *mtd, void *param)
 +static void fixup_unlock_powerup_lock(struct mtd_info *mtd, void *param)
  {
 -      printk(KERN_INFO "Using auto-unlock on power-up/resume\n" );
 -      mtd->flags |= MTD_STUPID_LOCK;
 +      struct map_info *map = mtd->priv;
 +      struct cfi_private *cfi = map->fldrv_priv;
 +      struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
 +
 +      if (cfip->FeatureSupport&32) {
 +              printk(KERN_INFO "Using auto-unlock on power-up/resume\n" );
 +              mtd->flags |= MTD_POWERUP_LOCK;
 +      }
  }
  
  static struct cfi_fixup cfi_fixup_table[] = {
 +      { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
  #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
        { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
  #endif
  #endif
        { CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
        { CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
 -      { MANUFACTURER_INTEL, 0x891c,         fixup_use_powerup_lock, NULL, },
 +      { MANUFACTURER_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock, NULL, },
        { 0, 0, NULL, NULL }
  };
  
@@@ -326,7 -277,7 +326,7 @@@ read_pri_intelext(struct map_info *map
                return NULL;
  
        if (extp->MajorVersion != '1' ||
 -          (extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
 +          (extp->MinorVersion < '0' || extp->MinorVersion > '5')) {
                printk(KERN_ERR "  Unknown Intel/Sharp Extended Query "
                       "version %c.%c.\n",  extp->MajorVersion,
                       extp->MinorVersion);
@@@ -801,7 -752,6 +801,7 @@@ static int chip_ready (struct map_info 
  static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
  {
        int ret;
 +      DECLARE_WAITQUEUE(wait, current);
  
   retry:
        if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING
                        spin_unlock(contender->mutex);
                }
  
 +              /* Check if we already have suspended erase
 +               * on this chip. Sleep. */
 +              if (mode == FL_ERASING && shared->erasing
 +                  && shared->erasing->oldstate == FL_ERASING) {
 +                      spin_unlock(&shared->lock);
 +                      set_current_state(TASK_UNINTERRUPTIBLE);
 +                      add_wait_queue(&chip->wq, &wait);
 +                      spin_unlock(chip->mutex);
 +                      schedule();
 +                      remove_wait_queue(&chip->wq, &wait);
 +                      spin_lock(chip->mutex);
 +                      goto retry;
 +              }
 +
                /* We now own it */
                shared->writing = chip;
                if (mode == FL_ERASING)
@@@ -1568,9 -1504,12 +1568,12 @@@ static int __xipram do_write_buffer(str
        int ret, wbufsize, word_gap, words;
        const struct kvec *vec;
        unsigned long vec_seek;
+       unsigned long initial_adr;
+       int initial_len = len;
  
        wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
        adr += chip->start;
+       initial_adr = adr;
        cmd_adr = adr & ~(wbufsize-1);
  
        /* Let's determine this according to the interleave only once */
                return ret;
        }
  
-       XIP_INVAL_CACHED_RANGE(map, adr, len);
+       XIP_INVAL_CACHED_RANGE(map, initial_adr, initial_len);
        ENABLE_VPP(map);
        xip_disable(map, chip, cmd_adr);
  
        chip->state = FL_WRITING;
  
        ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
-                                  adr, len,
+                                  initial_adr, initial_len,
                                   chip->buffer_write_time);
        if (ret) {
                map_write(map, CMD(0x70), cmd_adr);
@@@ -2355,7 -2294,7 +2358,7 @@@ static int cfi_intelext_suspend(struct 
        struct flchip *chip;
        int ret = 0;
  
 -      if ((mtd->flags & MTD_STUPID_LOCK)
 +      if ((mtd->flags & MTD_POWERUP_LOCK)
            && extp && (extp->FeatureSupport & (1 << 5)))
                cfi_intelext_save_locks(mtd);
  
@@@ -2466,7 -2405,7 +2469,7 @@@ static void cfi_intelext_resume(struct 
                spin_unlock(chip->mutex);
        }
  
 -      if ((mtd->flags & MTD_STUPID_LOCK)
 +      if ((mtd->flags & MTD_POWERUP_LOCK)
            && extp && (extp->FeatureSupport & (1 << 5)))
                cfi_intelext_restore_locks(mtd);
  }
diff --combined drivers/mtd/mtdchar.c
index b42553cd9af5378c7ed09ccfce92c0c260fcd6f0,a0cee86464cae51646b148939d49b6c61b8725a1..5d3ac512ce169f1f4efc8de2cde7ae6ca21c6148
@@@ -27,12 -27,10 +27,10 @@@ static void mtd_notify_add(struct mtd_i
        if (!mtd)
                return;
  
-       class_device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2),
-                           NULL, "mtd%d", mtd->index);
+       device_create(mtd_class, NULL, MKDEV(MTD_CHAR_MAJOR, mtd->index*2), "mtd%d", mtd->index);
  
-       class_device_create(mtd_class, NULL,
-                           MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1),
-                           NULL, "mtd%dro", mtd->index);
+       device_create(mtd_class, NULL,
+                     MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1), "mtd%dro", mtd->index);
  }
  
  static void mtd_notify_remove(struct mtd_info* mtd)
@@@ -40,8 -38,8 +38,8 @@@
        if (!mtd)
                return;
  
-       class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2));
-       class_device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1));
+       device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2));
+       device_destroy(mtd_class, MKDEV(MTD_CHAR_MAJOR, mtd->index*2+1));
  }
  
  static struct mtd_notifier notifier = {
@@@ -483,7 -481,6 +481,7 @@@ static int mtd_ioctl(struct inode *inod
        {
                struct mtd_oob_buf buf;
                struct mtd_oob_ops ops;
 +              uint32_t retlen;
  
                if(!(file->f_mode & 2))
                        return -EPERM;
                buf.start &= ~(mtd->oobsize - 1);
                ret = mtd->write_oob(mtd, buf.start, &ops);
  
 -              if (copy_to_user(argp + sizeof(uint32_t), &ops.oobretlen,
 -                               sizeof(uint32_t)))
 +              if (ops.oobretlen > 0xFFFFFFFFU)
 +                      ret = -EOVERFLOW;
 +              retlen = ops.oobretlen;
 +              if (copy_to_user(&((struct mtd_oob_buf *)argp)->length,
 +                               &retlen, sizeof(buf.length)))
                        ret = -EFAULT;
  
                kfree(ops.oobbuf);