Merge remote-tracking branch 'kernel-2.6.32/develop' into develop-2.6.36
author黄涛 <huangtao@rock-chips.com>
Thu, 27 Oct 2011 10:40:06 +0000 (18:40 +0800)
committer黄涛 <huangtao@rock-chips.com>
Thu, 27 Oct 2011 10:40:06 +0000 (18:40 +0800)
Conflicts:
drivers/media/video/rk29_camera_oneframe.c
drivers/mmc/core/core.c
drivers/usb/gadget/f_mass_storage.c
include/linux/mmc/host.h

24 files changed:
1  2 
arch/arm/mach-rk29/board-rk29-ddr3sdk.c
arch/arm/mach-rk29/board-rk29-phonesdk.c
arch/arm/mach-rk29/board-rk29phonepadsdk.c
arch/arm/mach-rk29/board-rk29sdk.c
arch/arm/mach-rk29/vpu_service.c
drivers/i2c/busses/i2c-rk29.c
drivers/media/video/rk29_camera.c
drivers/media/video/rk29_camera_oneframe.c
drivers/media/video/soc_camera.c
drivers/mmc/core/core.c
drivers/mmc/core/sdio.c
drivers/mmc/host/Kconfig
drivers/mmc/host/rk29_sdmmc.c
drivers/mmc/host/rk29_sdmmc_old.c
drivers/usb/dwc_otg/dwc_otg_hcd.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/storage_common.c
drivers/video/Kconfig
drivers/video/rk29_fb.c
include/linux/mmc/host.h
include/media/soc_camera.h
sound/soc/codecs/wm8900.c
sound/soc/rk29/rk29_i2s.c
sound/soc/rk29/rk29_pcm.c

Simple merge
Simple merge
Simple merge
Simple merge
index 8271743402efff503ed5fac934d27df05fe7ad32,884ae3db704ac7fec5ab5b511dc0504d129c9445..ff63a0c3e2779defeba43fb3ff1116bca11ec6e9
@@@ -131,7 -130,7 +131,7 @@@ module_param(debug, int, S_IRUGO|S_IWUS
  #define CAM_IPPWORK_IS_EN()     ((pcdev->host_width != pcdev->icd->user_width) || (pcdev->host_height != pcdev->icd->user_height))                                  
  
  //Configure Macro
- #define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 2)
 -#define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 0, 3)
++#define RK29_CAM_VERSION_CODE KERNEL_VERSION(0, 1, 3)
  
  /* limit to rk29 hardware capabilities */
  #define RK29_CAM_BUS_PARAM   (SOCAM_MASTER |\
Simple merge
index 75ae6fe27e3688a50ab0e3184db73ee8fcefb311,20f9b82b0d53fe9ca81a783a11a7e7a37add203b..b90497f93be22ee2a7322890e78532cf91eaf297
@@@ -1091,353 -1102,7 +1124,354 @@@ void mmc_detect_change(struct mmc_host 
  
  EXPORT_SYMBOL(mmc_detect_change);
  
 +void mmc_init_erase(struct mmc_card *card)
 +{
 +      unsigned int sz;
 +
 +      if (is_power_of_2(card->erase_size))
 +              card->erase_shift = ffs(card->erase_size) - 1;
 +      else
 +              card->erase_shift = 0;
 +
 +      /*
 +       * It is possible to erase an arbitrarily large area of an SD or MMC
 +       * card.  That is not desirable because it can take a long time
 +       * (minutes) potentially delaying more important I/O, and also the
 +       * timeout calculations become increasingly hugely over-estimated.
 +       * Consequently, 'pref_erase' is defined as a guide to limit erases
 +       * to that size and alignment.
 +       *
 +       * For SD cards that define Allocation Unit size, limit erases to one
 +       * Allocation Unit at a time.  For MMC cards that define High Capacity
 +       * Erase Size, whether it is switched on or not, limit to that size.
 +       * Otherwise just have a stab at a good value.  For modern cards it
 +       * will end up being 4MiB.  Note that if the value is too small, it
 +       * can end up taking longer to erase.
 +       */
 +      if (mmc_card_sd(card) && card->ssr.au) {
 +              card->pref_erase = card->ssr.au;
 +              card->erase_shift = ffs(card->ssr.au) - 1;
 +      } else if (card->ext_csd.hc_erase_size) {
 +              card->pref_erase = card->ext_csd.hc_erase_size;
 +      } else {
 +              sz = (card->csd.capacity << (card->csd.read_blkbits - 9)) >> 11;
 +              if (sz < 128)
 +                      card->pref_erase = 512 * 1024 / 512;
 +              else if (sz < 512)
 +                      card->pref_erase = 1024 * 1024 / 512;
 +              else if (sz < 1024)
 +                      card->pref_erase = 2 * 1024 * 1024 / 512;
 +              else
 +                      card->pref_erase = 4 * 1024 * 1024 / 512;
 +              if (card->pref_erase < card->erase_size)
 +                      card->pref_erase = card->erase_size;
 +              else {
 +                      sz = card->pref_erase % card->erase_size;
 +                      if (sz)
 +                              card->pref_erase += card->erase_size - sz;
 +              }
 +      }
 +}
 +
 +static void mmc_set_mmc_erase_timeout(struct mmc_card *card,
 +                                    struct mmc_command *cmd,
 +                                    unsigned int arg, unsigned int qty)
 +{
 +      unsigned int erase_timeout;
 +
 +      if (card->ext_csd.erase_group_def & 1) {
 +              /* High Capacity Erase Group Size uses HC timeouts */
 +              if (arg == MMC_TRIM_ARG)
 +                      erase_timeout = card->ext_csd.trim_timeout;
 +              else
 +                      erase_timeout = card->ext_csd.hc_erase_timeout;
 +      } else {
 +              /* CSD Erase Group Size uses write timeout */
 +              unsigned int mult = (10 << card->csd.r2w_factor);
 +              unsigned int timeout_clks = card->csd.tacc_clks * mult;
 +              unsigned int timeout_us;
 +
 +              /* Avoid overflow: e.g. tacc_ns=80000000 mult=1280 */
 +              if (card->csd.tacc_ns < 1000000)
 +                      timeout_us = (card->csd.tacc_ns * mult) / 1000;
 +              else
 +                      timeout_us = (card->csd.tacc_ns / 1000) * mult;
 +
 +              /*
 +               * ios.clock is only a target.  The real clock rate might be
 +               * less but not that much less, so fudge it by multiplying by 2.
 +               */
 +              timeout_clks <<= 1;
 +              timeout_us += (timeout_clks * 1000) /
 +                            (card->host->ios.clock / 1000);
 +
 +              erase_timeout = timeout_us / 1000;
 +
 +              /*
 +               * Theoretically, the calculation could underflow so round up
 +               * to 1ms in that case.
 +               */
 +              if (!erase_timeout)
 +                      erase_timeout = 1;
 +      }
 +
 +      /* Multiplier for secure operations */
 +      if (arg & MMC_SECURE_ARGS) {
 +              if (arg == MMC_SECURE_ERASE_ARG)
 +                      erase_timeout *= card->ext_csd.sec_erase_mult;
 +              else
 +                      erase_timeout *= card->ext_csd.sec_trim_mult;
 +      }
 +
 +      erase_timeout *= qty;
 +
 +      /*
 +       * Ensure at least a 1 second timeout for SPI as per
 +       * 'mmc_set_data_timeout()'
 +       */
 +      if (mmc_host_is_spi(card->host) && erase_timeout < 1000)
 +              erase_timeout = 1000;
 +
 +      cmd->erase_timeout = erase_timeout;
 +}
 +
 +static void mmc_set_sd_erase_timeout(struct mmc_card *card,
 +                                   struct mmc_command *cmd, unsigned int arg,
 +                                   unsigned int qty)
 +{
 +      if (card->ssr.erase_timeout) {
 +              /* Erase timeout specified in SD Status Register (SSR) */
 +              cmd->erase_timeout = card->ssr.erase_timeout * qty +
 +                                   card->ssr.erase_offset;
 +      } else {
 +              /*
 +               * Erase timeout not specified in SD Status Register (SSR) so
 +               * use 250ms per write block.
 +               */
 +              cmd->erase_timeout = 250 * qty;
 +      }
 +
 +      /* Must not be less than 1 second */
 +      if (cmd->erase_timeout < 1000)
 +              cmd->erase_timeout = 1000;
 +}
 +
 +static void mmc_set_erase_timeout(struct mmc_card *card,
 +                                struct mmc_command *cmd, unsigned int arg,
 +                                unsigned int qty)
 +{
 +      if (mmc_card_sd(card))
 +              mmc_set_sd_erase_timeout(card, cmd, arg, qty);
 +      else
 +              mmc_set_mmc_erase_timeout(card, cmd, arg, qty);
 +}
 +
 +static int mmc_do_erase(struct mmc_card *card, unsigned int from,
 +                      unsigned int to, unsigned int arg)
 +{
 +      struct mmc_command cmd;
 +      unsigned int qty = 0;
 +      int err;
 +
 +      /*
 +       * qty is used to calculate the erase timeout which depends on how many
 +       * erase groups (or allocation units in SD terminology) are affected.
 +       * We count erasing part of an erase group as one erase group.
 +       * For SD, the allocation units are always a power of 2.  For MMC, the
 +       * erase group size is almost certainly also power of 2, but it does not
 +       * seem to insist on that in the JEDEC standard, so we fall back to
 +       * division in that case.  SD may not specify an allocation unit size,
 +       * in which case the timeout is based on the number of write blocks.
 +       *
 +       * Note that the timeout for secure trim 2 will only be correct if the
 +       * number of erase groups specified is the same as the total of all
 +       * preceding secure trim 1 commands.  Since the power may have been
 +       * lost since the secure trim 1 commands occurred, it is generally
 +       * impossible to calculate the secure trim 2 timeout correctly.
 +       */
 +      if (card->erase_shift)
 +              qty += ((to >> card->erase_shift) -
 +                      (from >> card->erase_shift)) + 1;
 +      else if (mmc_card_sd(card))
 +              qty += to - from + 1;
 +      else
 +              qty += ((to / card->erase_size) -
 +                      (from / card->erase_size)) + 1;
 +
 +      if (!mmc_card_blockaddr(card)) {
 +              from <<= 9;
 +              to <<= 9;
 +      }
 +
 +      memset(&cmd, 0, sizeof(struct mmc_command));
 +      if (mmc_card_sd(card))
 +              cmd.opcode = SD_ERASE_WR_BLK_START;
 +      else
 +              cmd.opcode = MMC_ERASE_GROUP_START;
 +      cmd.arg = from;
 +      cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 +      err = mmc_wait_for_cmd(card->host, &cmd, 0);
 +      if (err) {
 +              printk(KERN_ERR "mmc_erase: group start error %d, "
 +                     "status %#x\n", err, cmd.resp[0]);
 +              err = -EINVAL;
 +              goto out;
 +      }
 +
 +      memset(&cmd, 0, sizeof(struct mmc_command));
 +      if (mmc_card_sd(card))
 +              cmd.opcode = SD_ERASE_WR_BLK_END;
 +      else
 +              cmd.opcode = MMC_ERASE_GROUP_END;
 +      cmd.arg = to;
 +      cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC;
 +      err = mmc_wait_for_cmd(card->host, &cmd, 0);
 +      if (err) {
 +              printk(KERN_ERR "mmc_erase: group end error %d, status %#x\n",
 +                     err, cmd.resp[0]);
 +              err = -EINVAL;
 +              goto out;
 +      }
 +
 +      memset(&cmd, 0, sizeof(struct mmc_command));
 +      cmd.opcode = MMC_ERASE;
 +      cmd.arg = arg;
 +      cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
 +      mmc_set_erase_timeout(card, &cmd, arg, qty);
 +      err = mmc_wait_for_cmd(card->host, &cmd, 0);
 +      if (err) {
 +              printk(KERN_ERR "mmc_erase: erase error %d, status %#x\n",
 +                     err, cmd.resp[0]);
 +              err = -EIO;
 +              goto out;
 +      }
 +
 +      if (mmc_host_is_spi(card->host))
 +              goto out;
 +
 +      do {
 +              memset(&cmd, 0, sizeof(struct mmc_command));
 +              cmd.opcode = MMC_SEND_STATUS;
 +              cmd.arg = card->rca << 16;
 +              cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
 +              /* Do not retry else we can't see errors */
 +              err = mmc_wait_for_cmd(card->host, &cmd, 0);
 +              if (err || (cmd.resp[0] & 0xFDF92000)) {
 +                      printk(KERN_ERR "error %d requesting status %#x\n",
 +                              err, cmd.resp[0]);
 +                      err = -EIO;
 +                      goto out;
 +              }
 +      } while (!(cmd.resp[0] & R1_READY_FOR_DATA) ||
 +               R1_CURRENT_STATE(cmd.resp[0]) == 7);
 +out:
 +      return err;
 +}
 +
 +/**
 + * mmc_erase - erase sectors.
 + * @card: card to erase
 + * @from: first sector to erase
 + * @nr: number of sectors to erase
 + * @arg: erase command argument (SD supports only %MMC_ERASE_ARG)
 + *
 + * Caller must claim host before calling this function.
 + */
 +int mmc_erase(struct mmc_card *card, unsigned int from, unsigned int nr,
 +            unsigned int arg)
 +{
 +      unsigned int rem, to = from + nr;
 +
 +      if (!(card->host->caps & MMC_CAP_ERASE) ||
 +          !(card->csd.cmdclass & CCC_ERASE))
 +              return -EOPNOTSUPP;
 +
 +      if (!card->erase_size)
 +              return -EOPNOTSUPP;
 +
 +      if (mmc_card_sd(card) && arg != MMC_ERASE_ARG)
 +              return -EOPNOTSUPP;
 +
 +      if ((arg & MMC_SECURE_ARGS) &&
 +          !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN))
 +              return -EOPNOTSUPP;
 +
 +      if ((arg & MMC_TRIM_ARGS) &&
 +          !(card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN))
 +              return -EOPNOTSUPP;
 +
 +      if (arg == MMC_SECURE_ERASE_ARG) {
 +              if (from % card->erase_size || nr % card->erase_size)
 +                      return -EINVAL;
 +      }
 +
 +      if (arg == MMC_ERASE_ARG) {
 +              rem = from % card->erase_size;
 +              if (rem) {
 +                      rem = card->erase_size - rem;
 +                      from += rem;
 +                      if (nr > rem)
 +                              nr -= rem;
 +                      else
 +                              return 0;
 +              }
 +              rem = nr % card->erase_size;
 +              if (rem)
 +                      nr -= rem;
 +      }
 +
 +      if (nr == 0)
 +              return 0;
 +
 +      to = from + nr;
 +
 +      if (to <= from)
 +              return -EINVAL;
 +
 +      /* 'from' and 'to' are inclusive */
 +      to -= 1;
 +
 +      return mmc_do_erase(card, from, to, arg);
 +}
 +EXPORT_SYMBOL(mmc_erase);
 +
 +int mmc_can_erase(struct mmc_card *card)
 +{
 +      if ((card->host->caps & MMC_CAP_ERASE) &&
 +          (card->csd.cmdclass & CCC_ERASE) && card->erase_size)
 +              return 1;
 +      return 0;
 +}
 +EXPORT_SYMBOL(mmc_can_erase);
 +
 +int mmc_can_trim(struct mmc_card *card)
 +{
 +      if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_GB_CL_EN)
 +              return 1;
 +      return 0;
 +}
 +EXPORT_SYMBOL(mmc_can_trim);
 +
 +int mmc_can_secure_erase_trim(struct mmc_card *card)
 +{
 +      if (card->ext_csd.sec_feature_support & EXT_CSD_SEC_ER_EN)
 +              return 1;
 +      return 0;
 +}
 +EXPORT_SYMBOL(mmc_can_secure_erase_trim);
 +
 +int mmc_erase_group_aligned(struct mmc_card *card, unsigned int from,
 +                          unsigned int nr)
 +{
 +      if (!card->erase_size)
 +              return 0;
 +      if (from % card->erase_size || nr % card->erase_size)
 +              return 0;
 +      return 1;
 +}
 +EXPORT_SYMBOL(mmc_erase_group_aligned);
 +
+ #if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)  
  void mmc_rescan(struct work_struct *work)
  {
        struct mmc_host *host =
                extend_wakelock = 1;
                goto out;
        }
+ #if !defined(CONFIG_USE_SDMMC0_FOR_WIFI_DEVELOP_BOARD)                
      }
-       
+ #endif
+     /*
+      * ...then normal SD...
+      */
+     err = mmc_send_app_op_cond(host, 0, &ocr);
+     if (!err) {
+       printk("\n%s..%d..  ===== Begin to identify card as SD-card ===xbw[%s]===\n",__FUNCTION__, __LINE__, mmc_hostname(host));
+       if (mmc_attach_sd(host, ocr))
+       {
+           printk("\n=====\n%s..%d..  ===== Initialize SD-card unsuccessfully!!! ===xbw[%s]===\n====\n",\
+               __FUNCTION__,  __LINE__, mmc_hostname(host));
+               
+               mmc_power_off(host);
+       }
+       else
+       {
+           printk("%s..%d..  ===== Initialize SD-card successfully. ===xbw[%s]===\n",__FUNCTION__,  __LINE__, mmc_hostname(host));
+       }
+       extend_wakelock = 1;
+       goto out;
+     }
+     /*
+      * ...and finally MMC.
+      */
+     err = mmc_send_op_cond(host, 0, &ocr);
+     if (!err) {
+         printk("\n%s..%d..  ===== Begin to identify card as MMC-card ===xbw[%s]===\n", __FUNCTION__, __LINE__, mmc_hostname(host));
+       if (mmc_attach_mmc(host, ocr))
+       {
+           printk("\n =====\n%s..%d..  ===== Initialize MMC-card unsuccessfully!!! ===xbw[%s]===\n======\n",\
+               __FUNCTION__,  __LINE__, mmc_hostname(host));
+               
+               mmc_power_off(host);
+       }
+       else
+       {
+           printk("%s...%d..  ===== Initialize MMC-card successfully. ===xbw[%s]===\n",__FUNCTION__,  __LINE__, mmc_hostname(host));
+       }
+       extend_wakelock = 1;
+       goto out;
+     }
+       mmc_release_host(host);
+       mmc_power_off(host);
+ out:
+       if (extend_wakelock)
+               wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2);
+       else
+               wake_unlock(&mmc_delayed_work_wake_lock);
+       if (host->caps & MMC_CAP_NEEDS_POLL)
+               mmc_schedule_delayed_work(&host->detect, HZ);
+ }
  #else
 -      int extend_wakelock = 0;
 -      
 -#if defined(CONFIG_SDMMC_RK29) && defined(CONFIG_SDMMC_RK29_OLD)      
+ void mmc_rescan(struct work_struct *work)
+ {
+       struct mmc_host *host =
+               container_of(work, struct mmc_host, detect.work);
+       u32 ocr;
+       int err;
 -#endif
+       unsigned long flags;
++      int extend_wakelock = 0;
+       spin_lock_irqsave(&host->lock, flags);
+       if (host->rescan_disable) {
+               spin_unlock_irqrestore(&host->lock, flags);
+               return;
+       }
+       spin_unlock_irqrestore(&host->lock, flags);
 -
+       mmc_bus_get(host);
+       /* if there is a card registered, check whether it is still present */
+       if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead)
+               host->bus_ops->detect(host);
+       /* If the card was removed the bus will be marked
+        * as dead - extend the wakelock so userspace
+        * can respond */
+       if (host->bus_dead)
+               extend_wakelock = 1;
+       mmc_bus_put(host);
+       mmc_bus_get(host);
+       /* if there still is a card present, stop here */
+       if (host->bus_ops != NULL) {
+               mmc_bus_put(host);
+               goto out;
+       }
+       /* detect a newly inserted card */
+       /*
+        * Only we can add a new handler, so it's safe to
+        * release the lock here.
+        */
+       mmc_bus_put(host);
 -
++      
+       if (host->ops->get_cd && host->ops->get_cd(host) == 0)
+               goto out;
+       mmc_claim_host(host);
+       mmc_power_up(host);
++      sdio_reset(host);
+       mmc_go_idle(host);
++      
        mmc_send_if_cond(host, host->ocr_avail);
  
        /*
         */
        err = mmc_send_io_op_cond(host, 0, &ocr);
        if (!err) {
 -              if (mmc_attach_sdio(host, ocr))
 -                      mmc_power_off(host);
 -              extend_wakelock = 1;
 +              if (mmc_attach_sdio(host, ocr)) {
 +                      mmc_claim_host(host);
 +                      /* try SDMEM (but not MMC) even if SDIO is broken */
 +                      if (mmc_send_app_op_cond(host, 0, &ocr))
 +                              goto out_fail;
 +
 +                      if (mmc_attach_sd(host, ocr))
 +                              mmc_power_off(host);
 +                      extend_wakelock = 1;
 +              }
                goto out;
        }
- #endif
  
        /*
         * ...then normal SD...
index b81f07ce69abd88e9b501621772649a3e936d94e,5e98695bae99dbf2e9d904fba4f76abe3bf2ca2a..da17bddc15fc6d08dea0e8060663dd74adbf9b15
mode 100644,100755..100755
Simple merge
Simple merge
Simple merge
Simple merge
index 7a3ddcf42edbc3fc51503bdc959d07b5d7ef6e78,79aad93fcdeb0be27a13b166ea31ff3a569647c2..3c78083bf57c25fb2a108bcf843c7dd8dcab9c5b
mode 100644,100755..100644
  
  #include "gadget_chips.h"
  
 -#define BULK_BUFFER_SIZE           16384 * 4//4096
 +#ifdef CONFIG_USB_ANDROID_MASS_STORAGE
 +#include <linux/usb/android_composite.h>
 +#include <linux/platform_device.h>
 +
 +#define FUNCTION_NAME         "usb_mass_storage"
 +#endif
  
 -/*-------------------------------------------------------------------------*/
 -
 -#define DRIVER_NAME           "usb_mass_storage"
 -#define MAX_LUNS              8
 -
 -static const char shortname[] = DRIVER_NAME;
 -
 -#ifdef DEBUG
 -#define LDBG(lun, fmt, args...) \
 -      dev_dbg(&(lun)->dev , fmt , ## args)
 -#define MDBG(fmt,args...) \
 -      printk(KERN_DEBUG DRIVER_NAME ": " fmt , ## args)
 -#else
 -#define LDBG(lun, fmt, args...) \
 -      do { } while (0)
 -#define MDBG(fmt,args...) \
 -      do { } while (0)
 -#undef VERBOSE_DEBUG
 -#undef DUMP_MSGS
 -#endif /* DEBUG */
 -
 -#ifdef VERBOSE_DEBUG
 -#define VLDBG LDBG
 -#else
 -#define VLDBG(lun, fmt, args...) \
 -      do { } while (0)
 -#endif /* VERBOSE_DEBUG */
 -
 -#define LERROR(lun, fmt, args...) \
 -      dev_err(&(lun)->dev , fmt , ## args)
 -#define LWARN(lun, fmt, args...) \
 -      dev_warn(&(lun)->dev , fmt , ## args)
 -#define LINFO(lun, fmt, args...) \
 -      dev_info(&(lun)->dev , fmt , ## args)
 -
 -#define MINFO(fmt,args...) \
 -      printk(KERN_INFO DRIVER_NAME ": " fmt , ## args)
 -
 -#undef DBG
 -#undef VDBG
 -#undef ERROR
 -#undef WARNING
 -#undef INFO
 -#define DBG(d, fmt, args...) \
 -      dev_dbg(&(d)->cdev->gadget->dev , fmt , ## args)
 -#define VDBG(d, fmt, args...) \
 -      dev_vdbg(&(d)->cdev->gadget->dev , fmt , ## args)
 -#define ERROR(d, fmt, args...) \
 -      dev_err(&(d)->cdev->gadget->dev , fmt , ## args)
 -#define WARNING(d, fmt, args...) \
 -      dev_warn(&(d)->cdev->gadget->dev , fmt , ## args)
 -#define INFO(d, fmt, args...) \
 -      dev_info(&(d)->cdev->gadget->dev , fmt , ## args)
 -
 -
 -/*-------------------------------------------------------------------------*/
 -
 -/* Bulk-only data structures */
 -
 -/* Command Block Wrapper */
 -struct bulk_cb_wrap {
 -      __le32  Signature;              /* Contains 'USBC' */
 -      u32     Tag;                    /* Unique per command id */
 -      __le32  DataTransferLength;     /* Size of the data */
 -      u8      Flags;                  /* Direction in bit 7 */
 -      u8      Lun;                    /* LUN (normally 0) */
 -      u8      Length;                 /* Of the CDB, <= MAX_COMMAND_SIZE */
 -      u8      CDB[16];                /* Command Data Block */
 -};
 -
 -#define USB_BULK_CB_WRAP_LEN  31
 -#define USB_BULK_CB_SIG               0x43425355      /* Spells out USBC */
 -#define USB_BULK_IN_FLAG      0x80
 -
 -/* Command Status Wrapper */
 -struct bulk_cs_wrap {
 -      __le32  Signature;              /* Should = 'USBS' */
 -      u32     Tag;                    /* Same as original command */
 -      __le32  Residue;                /* Amount not transferred */
 -      u8      Status;                 /* See below */
 -};
 -
 -#define USB_BULK_CS_WRAP_LEN  13
 -#define USB_BULK_CS_SIG               0x53425355      /* Spells out 'USBS' */
 -#define USB_STATUS_PASS               0
 -#define USB_STATUS_FAIL               1
 -#define USB_STATUS_PHASE_ERROR        2
 -
 -/* Bulk-only class specific requests */
 -#define USB_BULK_RESET_REQUEST                0xff
 -#define USB_BULK_GET_MAX_LUN_REQUEST  0xfe
 -
 -/* Length of a SCSI Command Data Block */
 -#define MAX_COMMAND_SIZE      16
 -
 -/* SCSI commands that we recognize */
 -#define SC_FORMAT_UNIT                        0x04
 -#define SC_INQUIRY                    0x12
 -#define SC_MODE_SELECT_6              0x15
 -#define SC_MODE_SELECT_10             0x55
 -#define SC_MODE_SENSE_6                       0x1a
 -#define SC_MODE_SENSE_10              0x5a
 -#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL       0x1e
 -#define SC_READ_6                     0x08
 -#define SC_READ_10                    0x28
 -#define SC_READ_12                    0xa8
 -#define SC_READ_CAPACITY              0x25
 -#define SC_READ_FORMAT_CAPACITIES     0x23
 -#define SC_RELEASE                    0x17
 -#define SC_REQUEST_SENSE              0x03
 -#define SC_RESERVE                    0x16
 -#define SC_SEND_DIAGNOSTIC            0x1d
 -#define SC_START_STOP_UNIT            0x1b
 -#define SC_SYNCHRONIZE_CACHE          0x35
 -#define SC_TEST_UNIT_READY            0x00
 -#define SC_VERIFY                     0x2f
 -#define SC_WRITE_6                    0x0a
 -#define SC_WRITE_10                   0x2a
 -#define SC_WRITE_12                   0xaa
 -
 -/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
 -#define SS_NO_SENSE                           0
 -#define SS_COMMUNICATION_FAILURE              0x040800
 -#define SS_INVALID_COMMAND                    0x052000
 -#define SS_INVALID_FIELD_IN_CDB                       0x052400
 -#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100
 -#define SS_LOGICAL_UNIT_NOT_SUPPORTED         0x052500
 -#define SS_MEDIUM_NOT_PRESENT                 0x023a00
 -#define SS_MEDIUM_REMOVAL_PREVENTED           0x055302
 -#define SS_NOT_READY_TO_READY_TRANSITION      0x062800
 -#define SS_RESET_OCCURRED                     0x062900
 -#define SS_SAVING_PARAMETERS_NOT_SUPPORTED    0x053900
 -#define SS_UNRECOVERED_READ_ERROR             0x031100
 -#define SS_WRITE_ERROR                                0x030c02
 -#define SS_WRITE_PROTECTED                    0x072700
 -
 -#define SK(x)         ((u8) ((x) >> 16))      /* Sense Key byte, etc. */
 -#define ASC(x)                ((u8) ((x) >> 8))
 -#define ASCQ(x)               ((u8) (x))
 -
 -static  int usb_msc_connected;        /*usb charge status*/
 -/*-------------------------------------------------------------------------*/
 -
 -struct lun {
 -      struct file     *filp;
 -      loff_t          file_length;
 -      loff_t          num_sectors;
 -      unsigned int unflushed_packet;
 -      unsigned int unflushed_bytes;
 -
 -      unsigned int    ro : 1;
 -      unsigned int    prevent_medium_removal : 1;
 -      unsigned int    registered : 1;
 -      unsigned int    info_valid : 1;
 -
 -      u32             sense_data;
 -      u32             sense_data_info;
 -      u32             unit_attention_data;
 -
 -      struct device   dev;
 -};
 -
 -#define backing_file_is_open(curlun)  ((curlun)->filp != NULL)
 +#ifdef CONFIG_ARCH_RK29
+ /* flush after every 4 meg of writes to avoid excessive block level caching */
+ #define MAX_UNFLUSHED_BYTES  (64 * 1024)// (4 * 1024 * 1024) //original value is 4MB,Modifyed by xbw at 2011-08-18
+ #define MAX_UNFLUSHED_PACKETS 4//16
 +#include <linux/power_supply.h>
 +#include <linux/reboot.h>
 +#include <linux/syscalls.h>
  
 +static int usb_msc_connected; /*usb charge status*/
  
 -static struct lun *dev_to_lun(struct device *dev)
 +static void set_msc_connect_flag( int connected )
  {
 -      return container_of(dev, struct lun, dev);
 +      printk("%s status = %d 20101216\n" , __func__, connected);
 +      if( usb_msc_connected == connected )
 +              return;
 +      usb_msc_connected = connected;//usb mass storage is ok
  }
  
 -/* Big enough to hold our biggest descriptor */
 -#define EP0_BUFSIZE   256
 +int get_msc_connect_flag( void )
 +{
 +      return usb_msc_connected;
 +}
 +EXPORT_SYMBOL(get_msc_connect_flag);
 +#endif
  
 -/* Number of buffers we will use.  2 is enough for double-buffering */
 -#define NUM_BUFFERS   2
 +/*------------------------------------------------------------------------*/
  
 -enum fsg_buffer_state {
 -      BUF_STATE_EMPTY = 0,
 -      BUF_STATE_FULL,
 -      BUF_STATE_BUSY
 -};
 +#define FSG_DRIVER_DESC               "Mass Storage Function"
 +#define FSG_DRIVER_VERSION    "2009/09/11"
  
 -struct fsg_buffhd {
 -      void                            *buf;
 -      enum fsg_buffer_state           state;
 -      struct fsg_buffhd               *next;
 +static const char fsg_string_interface[] = "Mass Storage";
  
 -      /* The NetChip 2280 is faster, and handles some protocol faults
 -       * better, if we don't submit any short bulk-out read requests.
 -       * So we will record the intended request length here. */
 -      unsigned int                    bulk_out_intended_length;
  
 -      struct usb_request              *inreq;
 -      int                             inreq_busy;
 -      struct usb_request              *outreq;
 -      int                             outreq_busy;
 -};
 +#define FSG_NO_INTR_EP 1
 +#define FSG_NO_DEVICE_STRINGS    1
 +#define FSG_NO_OTG               1
 +#define FSG_NO_INTR_EP           1
  
 -enum fsg_state {
 -      /* This one isn't used anywhere */
 -      FSG_STATE_COMMAND_PHASE = -10,
 +#include "storage_common.c"
  
 -      FSG_STATE_DATA_PHASE,
 -      FSG_STATE_STATUS_PHASE,
  
 -      FSG_STATE_IDLE = 0,
 -      FSG_STATE_ABORT_BULK_OUT,
 -      FSG_STATE_RESET,
 -      FSG_STATE_CONFIG_CHANGE,
 -      FSG_STATE_EXIT,
 -      FSG_STATE_TERMINATED
 -};
 +/*-------------------------------------------------------------------------*/
  
 -enum data_direction {
 -      DATA_DIR_UNKNOWN = 0,
 -      DATA_DIR_FROM_HOST,
 -      DATA_DIR_TO_HOST,
 -      DATA_DIR_NONE
 +struct fsg_dev;
 +struct fsg_common;
 +
 +/* FSF callback functions */
 +struct fsg_operations {
 +      /* Callback function to call when thread exits.  If no
 +       * callback is set or it returns value lower then zero MSF
 +       * will force eject all LUNs it operates on (including those
 +       * marked as non-removable or with prevent_medium_removal flag
 +       * set). */
 +      int (*thread_exits)(struct fsg_common *common);
 +
 +      /* Called prior to ejection.  Negative return means error,
 +       * zero means to continue with ejection, positive means not to
 +       * eject. */
 +      int (*pre_eject)(struct fsg_common *common,
 +                       struct fsg_lun *lun, int num);
 +      /* Called after ejection.  Negative return means error, zero
 +       * or positive is just a success. */
 +      int (*post_eject)(struct fsg_common *common,
 +                        struct fsg_lun *lun, int num);
  };
  
 -struct fsg_dev {
 -      struct usb_function function;
 -      struct usb_composite_dev *cdev;
 -
 -      /* optional "usb_mass_storage" platform device */
 -      struct platform_device *pdev;
  
 -      /* lock protects: state and all the req_busy's */
 -      spinlock_t              lock;
 +/* Data shared by all the FSG instances. */
 +struct fsg_common {
 +      struct usb_gadget       *gadget;
 +      struct fsg_dev          *fsg, *new_fsg;
 +      wait_queue_head_t       fsg_wait;
  
        /* filesem protects: backing files in use */
        struct rw_semaphore     filesem;
@@@ -1059,8 -1078,17 +1063,17 @@@ static int do_write(struct fsg_common *
                        }
                        file_offset += nwritten;
                        amount_left_to_write -= nwritten;
 -                      fsg->residue -= nwritten;
 +                      common->residue -= nwritten;
  
 -                              fsync_sub(curlun);
+ #ifdef MAX_UNFLUSHED_PACKETS
+                       curlun->unflushed_packet ++;
+                       curlun->unflushed_bytes += nwritten;
+                       if( (curlun->unflushed_packet >= MAX_UNFLUSHED_PACKETS) || (curlun->unflushed_bytes >= MAX_UNFLUSHED_BYTES)) {
++                              fsg_lun_fsync_sub(curlun);
+                               curlun->unflushed_packet = 0;
+                               curlun->unflushed_bytes = 0;
+                       }
+ #endif
                        /* If an error occurred, report it and its position */
                        if (nwritten < amount) {
                                curlun->sense_data = SS_WRITE_ERROR;
index 7e3d5599b8980b2cbc458a16780e208e1c787afb,0000000000000000000000000000000000000000..5bf801b1c8bc7d99e14c14209c7775256554a204
mode 100644,000000..100644
--- /dev/null
@@@ -1,842 -1,0 +1,846 @@@
 +/*
 + * storage_common.c -- Common definitions for mass storage functionality
 + *
 + * Copyright (C) 2003-2008 Alan Stern
 + * Copyeight (C) 2009 Samsung Electronics
 + * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License as published by
 + * the Free Software Foundation; either version 2 of the License, or
 + * (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License
 + * along with this program; if not, write to the Free Software
 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 + */
 +
 +
 +/*
 + * This file requires the following identifiers used in USB strings to
 + * be defined (each of type pointer to char):
 + *  - fsg_string_manufacturer -- name of the manufacturer
 + *  - fsg_string_product      -- name of the product
 + *  - fsg_string_serial       -- product's serial
 + *  - fsg_string_config       -- name of the configuration
 + *  - fsg_string_interface    -- name of the interface
 + * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS
 + * macro is defined prior to including this file.
 + */
 +
 +/*
 + * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and
 + * fsg_hs_intr_in_desc objects as well as
 + * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES
 + * macros are not defined.
 + *
 + * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER,
 + * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not
 + * defined (as well as corresponding entries in string tables are
 + * missing) and FSG_STRING_INTERFACE has value of zero.
 + *
 + * When FSG_NO_OTG is defined fsg_otg_desc won't be defined.
 + */
 +
 +/*
 + * When FSG_BUFFHD_STATIC_BUFFER is defined when this file is included
 + * the fsg_buffhd structure's buf field will be an array of FSG_BUFLEN
 + * characters rather then a pointer to void.
 + */
 +
 +
 +#include <asm/unaligned.h>
 +
 +
 +/*
 + * Thanks to NetChip Technologies for donating this product ID.
 + *
 + * DO NOT REUSE THESE IDs with any other driver!!  Ever!!
 + * Instead:  allocate your own, using normal USB-IF procedures.
 + */
 +#define FSG_VENDOR_ID 0x0525  /* NetChip */
 +#define FSG_PRODUCT_ID        0xa4a5  /* Linux-USB File-backed Storage Gadget */
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +
 +#ifndef DEBUG
 +#undef VERBOSE_DEBUG
 +#undef DUMP_MSGS
 +#endif /* !DEBUG */
 +
 +#ifdef VERBOSE_DEBUG
 +#define VLDBG LDBG
 +#else
 +#define VLDBG(lun, fmt, args...) do { } while (0)
 +#endif /* VERBOSE_DEBUG */
 +
 +#define LDBG(lun, fmt, args...)   dev_dbg (&(lun)->dev, fmt, ## args)
 +#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args)
 +#define LWARN(lun, fmt, args...)  dev_warn(&(lun)->dev, fmt, ## args)
 +#define LINFO(lun, fmt, args...)  dev_info(&(lun)->dev, fmt, ## args)
 +
 +/*
 + * Keep those macros in sync with those in
 + * include/linux/usb/composite.h or else GCC will complain.  If they
 + * are identical (the same names of arguments, white spaces in the
 + * same places) GCC will allow redefinition otherwise (even if some
 + * white space is removed or added) warning will be issued.
 + *
 + * Those macros are needed here because File Storage Gadget does not
 + * include the composite.h header.  For composite gadgets those macros
 + * are redundant since composite.h is included any way.
 + *
 + * One could check whether those macros are already defined (which
 + * would indicate composite.h had been included) or not (which would
 + * indicate we were in FSG) but this is not done because a warning is
 + * desired if definitions here differ from the ones in composite.h.
 + *
 + * We want the definitions to match and be the same in File Storage
 + * Gadget as well as Mass Storage Function (and so composite gadgets
 + * using MSF).  If someone changes them in composite.h it will produce
 + * a warning in this file when building MSF.
 + */
 +#define DBG(d, fmt, args...)     dev_dbg(&(d)->gadget->dev , fmt , ## args)
 +#define VDBG(d, fmt, args...)    dev_vdbg(&(d)->gadget->dev , fmt , ## args)
 +#define ERROR(d, fmt, args...)   dev_err(&(d)->gadget->dev , fmt , ## args)
 +#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args)
 +#define INFO(d, fmt, args...)    dev_info(&(d)->gadget->dev , fmt , ## args)
 +
 +
 +
 +#ifdef DUMP_MSGS
 +
 +#  define dump_msg(fsg, /* const char * */ label,                     \
 +                 /* const u8 * */ buf, /* unsigned */ length) do {    \
 +      if (length < 512) {                                             \
 +              DBG(fsg, "%s, length %u:\n", label, length);            \
 +              print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET,      \
 +                             16, 1, buf, length, 0);                  \
 +      }                                                               \
 +} while (0)
 +
 +#  define dump_cdb(fsg) do { } while (0)
 +
 +#else
 +
 +#  define dump_msg(fsg, /* const char * */ label, \
 +                 /* const u8 * */ buf, /* unsigned */ length) do { } while (0)
 +
 +#  ifdef VERBOSE_DEBUG
 +
 +#    define dump_cdb(fsg)                                             \
 +      print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE,      \
 +                     16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0)         \
 +
 +#  else
 +
 +#    define dump_cdb(fsg) do { } while (0)
 +
 +#  endif /* VERBOSE_DEBUG */
 +
 +#endif /* DUMP_MSGS */
 +
 +
 +
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +/* SCSI device types */
 +#define TYPE_DISK     0x00
 +#define TYPE_CDROM    0x05
 +
 +/* USB protocol value = the transport method */
 +#define USB_PR_CBI    0x00            /* Control/Bulk/Interrupt */
 +#define USB_PR_CB     0x01            /* Control/Bulk w/o interrupt */
 +#define USB_PR_BULK   0x50            /* Bulk-only */
 +
 +/* USB subclass value = the protocol encapsulation */
 +#define USB_SC_RBC    0x01            /* Reduced Block Commands (flash) */
 +#define USB_SC_8020   0x02            /* SFF-8020i, MMC-2, ATAPI (CD-ROM) */
 +#define USB_SC_QIC    0x03            /* QIC-157 (tape) */
 +#define USB_SC_UFI    0x04            /* UFI (floppy) */
 +#define USB_SC_8070   0x05            /* SFF-8070i (removable) */
 +#define USB_SC_SCSI   0x06            /* Transparent SCSI */
 +
 +/* Bulk-only data structures */
 +
 +/* Command Block Wrapper */
 +struct fsg_bulk_cb_wrap {
 +      __le32  Signature;              /* Contains 'USBC' */
 +      u32     Tag;                    /* Unique per command id */
 +      __le32  DataTransferLength;     /* Size of the data */
 +      u8      Flags;                  /* Direction in bit 7 */
 +      u8      Lun;                    /* LUN (normally 0) */
 +      u8      Length;                 /* Of the CDB, <= MAX_COMMAND_SIZE */
 +      u8      CDB[16];                /* Command Data Block */
 +};
 +
 +#define USB_BULK_CB_WRAP_LEN  31
 +#define USB_BULK_CB_SIG               0x43425355      /* Spells out USBC */
 +#define USB_BULK_IN_FLAG      0x80
 +
 +/* Command Status Wrapper */
 +struct bulk_cs_wrap {
 +      __le32  Signature;              /* Should = 'USBS' */
 +      u32     Tag;                    /* Same as original command */
 +      __le32  Residue;                /* Amount not transferred */
 +      u8      Status;                 /* See below */
 +};
 +
 +#define USB_BULK_CS_WRAP_LEN  13
 +#define USB_BULK_CS_SIG               0x53425355      /* Spells out 'USBS' */
 +#define USB_STATUS_PASS               0
 +#define USB_STATUS_FAIL               1
 +#define USB_STATUS_PHASE_ERROR        2
 +
 +/* Bulk-only class specific requests */
 +#define USB_BULK_RESET_REQUEST                0xff
 +#define USB_BULK_GET_MAX_LUN_REQUEST  0xfe
 +
 +
 +/* CBI Interrupt data structure */
 +struct interrupt_data {
 +      u8      bType;
 +      u8      bValue;
 +};
 +
 +#define CBI_INTERRUPT_DATA_LEN                2
 +
 +/* CBI Accept Device-Specific Command request */
 +#define USB_CBI_ADSC_REQUEST          0x00
 +
 +
 +/* Length of a SCSI Command Data Block */
 +#define MAX_COMMAND_SIZE      16
 +
 +/* SCSI commands that we recognize */
 +#define SC_FORMAT_UNIT                        0x04
 +#define SC_INQUIRY                    0x12
 +#define SC_MODE_SELECT_6              0x15
 +#define SC_MODE_SELECT_10             0x55
 +#define SC_MODE_SENSE_6                       0x1a
 +#define SC_MODE_SENSE_10              0x5a
 +#define SC_PREVENT_ALLOW_MEDIUM_REMOVAL       0x1e
 +#define SC_READ_6                     0x08
 +#define SC_READ_10                    0x28
 +#define SC_READ_12                    0xa8
 +#define SC_READ_CAPACITY              0x25
 +#define SC_READ_FORMAT_CAPACITIES     0x23
 +#define SC_READ_HEADER                        0x44
 +#define SC_READ_TOC                   0x43
 +#define SC_RELEASE                    0x17
 +#define SC_REQUEST_SENSE              0x03
 +#define SC_RESERVE                    0x16
 +#define SC_SEND_DIAGNOSTIC            0x1d
 +#define SC_START_STOP_UNIT            0x1b
 +#define SC_SYNCHRONIZE_CACHE          0x35
 +#define SC_TEST_UNIT_READY            0x00
 +#define SC_VERIFY                     0x2f
 +#define SC_WRITE_6                    0x0a
 +#define SC_WRITE_10                   0x2a
 +#define SC_WRITE_12                   0xaa
 +
 +/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
 +#define SS_NO_SENSE                           0
 +#define SS_COMMUNICATION_FAILURE              0x040800
 +#define SS_INVALID_COMMAND                    0x052000
 +#define SS_INVALID_FIELD_IN_CDB                       0x052400
 +#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100
 +#define SS_LOGICAL_UNIT_NOT_SUPPORTED         0x052500
 +#define SS_MEDIUM_NOT_PRESENT                 0x023a00
 +#define SS_MEDIUM_REMOVAL_PREVENTED           0x055302
 +#define SS_NOT_READY_TO_READY_TRANSITION      0x062800
 +#define SS_RESET_OCCURRED                     0x062900
 +#define SS_SAVING_PARAMETERS_NOT_SUPPORTED    0x053900
 +#define SS_UNRECOVERED_READ_ERROR             0x031100
 +#define SS_WRITE_ERROR                                0x030c02
 +#define SS_WRITE_PROTECTED                    0x072700
 +
 +#define SK(x)         ((u8) ((x) >> 16))      /* Sense Key byte, etc. */
 +#define ASC(x)                ((u8) ((x) >> 8))
 +#define ASCQ(x)               ((u8) (x))
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +
 +struct fsg_lun {
 +      struct file     *filp;
 +      loff_t          file_length;
 +      loff_t          num_sectors;
++#ifdef MAX_UNFLUSHED_PACKETS
++      unsigned int    unflushed_packet;
++      unsigned int    unflushed_bytes;
++#endif
 +
 +      unsigned int    initially_ro:1;
 +      unsigned int    ro:1;
 +      unsigned int    removable:1;
 +      unsigned int    cdrom:1;
 +      unsigned int    prevent_medium_removal:1;
 +      unsigned int    registered:1;
 +      unsigned int    info_valid:1;
 +      unsigned int    nofua:1;
 +
 +      u32             sense_data;
 +      u32             sense_data_info;
 +      u32             unit_attention_data;
 +
 +      struct device   dev;
 +};
 +
 +#define fsg_lun_is_open(curlun)       ((curlun)->filp != NULL)
 +
 +static struct fsg_lun *fsg_lun_from_dev(struct device *dev)
 +{
 +      return container_of(dev, struct fsg_lun, dev);
 +}
 +
 +
 +/* Big enough to hold our biggest descriptor */
 +#define EP0_BUFSIZE   256
 +#define DELAYED_STATUS        (EP0_BUFSIZE + 999)     /* An impossibly large value */
 +
 +/* Number of buffers we will use.  2 is enough for double-buffering */
 +#define FSG_NUM_BUFFERS       2
 +
 +/* Default size of buffer length. */
 +#define FSG_BUFLEN    ((u32)16384)
 +
 +/* Maximal number of LUNs supported in mass storage function */
 +#define FSG_MAX_LUNS  8
 +
 +enum fsg_buffer_state {
 +      BUF_STATE_EMPTY = 0,
 +      BUF_STATE_FULL,
 +      BUF_STATE_BUSY
 +};
 +
 +struct fsg_buffhd {
 +#ifdef FSG_BUFFHD_STATIC_BUFFER
 +      char                            buf[FSG_BUFLEN];
 +#else
 +      void                            *buf;
 +#endif
 +      enum fsg_buffer_state           state;
 +      struct fsg_buffhd               *next;
 +
 +      /*
 +       * The NetChip 2280 is faster, and handles some protocol faults
 +       * better, if we don't submit any short bulk-out read requests.
 +       * So we will record the intended request length here.
 +       */
 +      unsigned int                    bulk_out_intended_length;
 +
 +      struct usb_request              *inreq;
 +      int                             inreq_busy;
 +      struct usb_request              *outreq;
 +      int                             outreq_busy;
 +};
 +
 +enum fsg_state {
 +      /* This one isn't used anywhere */
 +      FSG_STATE_COMMAND_PHASE = -10,
 +      FSG_STATE_DATA_PHASE,
 +      FSG_STATE_STATUS_PHASE,
 +
 +      FSG_STATE_IDLE = 0,
 +      FSG_STATE_ABORT_BULK_OUT,
 +      FSG_STATE_RESET,
 +      FSG_STATE_INTERFACE_CHANGE,
 +      FSG_STATE_CONFIG_CHANGE,
 +      FSG_STATE_DISCONNECT,
 +      FSG_STATE_EXIT,
 +      FSG_STATE_TERMINATED
 +};
 +
 +enum data_direction {
 +      DATA_DIR_UNKNOWN = 0,
 +      DATA_DIR_FROM_HOST,
 +      DATA_DIR_TO_HOST,
 +      DATA_DIR_NONE
 +};
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +
 +static inline u32 get_unaligned_be24(u8 *buf)
 +{
 +      return 0xffffff & (u32) get_unaligned_be32(buf - 1);
 +}
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +
 +enum {
 +#ifndef FSG_NO_DEVICE_STRINGS
 +      FSG_STRING_MANUFACTURER = 1,
 +      FSG_STRING_PRODUCT,
 +      FSG_STRING_SERIAL,
 +      FSG_STRING_CONFIG,
 +#endif
 +      FSG_STRING_INTERFACE
 +};
 +
 +
 +#ifndef FSG_NO_OTG
 +static struct usb_otg_descriptor
 +fsg_otg_desc = {
 +      .bLength =              sizeof fsg_otg_desc,
 +      .bDescriptorType =      USB_DT_OTG,
 +
 +      .bmAttributes =         USB_OTG_SRP,
 +};
 +#endif
 +
 +/* There is only one interface. */
 +
 +static struct usb_interface_descriptor
 +fsg_intf_desc = {
 +      .bLength =              sizeof fsg_intf_desc,
 +      .bDescriptorType =      USB_DT_INTERFACE,
 +
 +      .bNumEndpoints =        2,              /* Adjusted during fsg_bind() */
 +      .bInterfaceClass =      USB_CLASS_MASS_STORAGE,
 +      .bInterfaceSubClass =   USB_SC_SCSI,    /* Adjusted during fsg_bind() */
 +      .bInterfaceProtocol =   USB_PR_BULK,    /* Adjusted during fsg_bind() */
 +      .iInterface =           FSG_STRING_INTERFACE,
 +};
 +
 +/*
 + * Three full-speed endpoint descriptors: bulk-in, bulk-out, and
 + * interrupt-in.
 + */
 +
 +static struct usb_endpoint_descriptor
 +fsg_fs_bulk_in_desc = {
 +      .bLength =              USB_DT_ENDPOINT_SIZE,
 +      .bDescriptorType =      USB_DT_ENDPOINT,
 +
 +      .bEndpointAddress =     USB_DIR_IN,
 +      .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 +      /* wMaxPacketSize set by autoconfiguration */
 +};
 +
 +static struct usb_endpoint_descriptor
 +fsg_fs_bulk_out_desc = {
 +      .bLength =              USB_DT_ENDPOINT_SIZE,
 +      .bDescriptorType =      USB_DT_ENDPOINT,
 +
 +      .bEndpointAddress =     USB_DIR_OUT,
 +      .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 +      /* wMaxPacketSize set by autoconfiguration */
 +};
 +
 +#ifndef FSG_NO_INTR_EP
 +
 +static struct usb_endpoint_descriptor
 +fsg_fs_intr_in_desc = {
 +      .bLength =              USB_DT_ENDPOINT_SIZE,
 +      .bDescriptorType =      USB_DT_ENDPOINT,
 +
 +      .bEndpointAddress =     USB_DIR_IN,
 +      .bmAttributes =         USB_ENDPOINT_XFER_INT,
 +      .wMaxPacketSize =       cpu_to_le16(2),
 +      .bInterval =            32,     /* frames -> 32 ms */
 +};
 +
 +#ifndef FSG_NO_OTG
 +#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES      2
 +#else
 +#  define FSG_FS_FUNCTION_PRE_EP_ENTRIES      1
 +#endif
 +
 +#endif
 +
 +static struct usb_descriptor_header *fsg_fs_function[] = {
 +#ifndef FSG_NO_OTG
 +      (struct usb_descriptor_header *) &fsg_otg_desc,
 +#endif
 +      (struct usb_descriptor_header *) &fsg_intf_desc,
 +      (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc,
 +      (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc,
 +#ifndef FSG_NO_INTR_EP
 +      (struct usb_descriptor_header *) &fsg_fs_intr_in_desc,
 +#endif
 +      NULL,
 +};
 +
 +
 +/*
 + * USB 2.0 devices need to expose both high speed and full speed
 + * descriptors, unless they only run at full speed.
 + *
 + * That means alternate endpoint descriptors (bigger packets)
 + * and a "device qualifier" ... plus more construction options
 + * for the configuration descriptor.
 + */
 +static struct usb_endpoint_descriptor
 +fsg_hs_bulk_in_desc = {
 +      .bLength =              USB_DT_ENDPOINT_SIZE,
 +      .bDescriptorType =      USB_DT_ENDPOINT,
 +
 +      /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */
 +      .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 +      .wMaxPacketSize =       cpu_to_le16(512),
 +};
 +
 +static struct usb_endpoint_descriptor
 +fsg_hs_bulk_out_desc = {
 +      .bLength =              USB_DT_ENDPOINT_SIZE,
 +      .bDescriptorType =      USB_DT_ENDPOINT,
 +
 +      /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */
 +      .bmAttributes =         USB_ENDPOINT_XFER_BULK,
 +      .wMaxPacketSize =       cpu_to_le16(512),
 +      .bInterval =            1,      /* NAK every 1 uframe */
 +};
 +
 +#ifndef FSG_NO_INTR_EP
 +
 +static struct usb_endpoint_descriptor
 +fsg_hs_intr_in_desc = {
 +      .bLength =              USB_DT_ENDPOINT_SIZE,
 +      .bDescriptorType =      USB_DT_ENDPOINT,
 +
 +      /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */
 +      .bmAttributes =         USB_ENDPOINT_XFER_INT,
 +      .wMaxPacketSize =       cpu_to_le16(2),
 +      .bInterval =            9,      /* 2**(9-1) = 256 uframes -> 32 ms */
 +};
 +
 +#ifndef FSG_NO_OTG
 +#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES      2
 +#else
 +#  define FSG_HS_FUNCTION_PRE_EP_ENTRIES      1
 +#endif
 +
 +#endif
 +
 +static struct usb_descriptor_header *fsg_hs_function[] = {
 +#ifndef FSG_NO_OTG
 +      (struct usb_descriptor_header *) &fsg_otg_desc,
 +#endif
 +      (struct usb_descriptor_header *) &fsg_intf_desc,
 +      (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc,
 +      (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc,
 +#ifndef FSG_NO_INTR_EP
 +      (struct usb_descriptor_header *) &fsg_hs_intr_in_desc,
 +#endif
 +      NULL,
 +};
 +
 +/* Maxpacket and other transfer characteristics vary by speed. */
 +static struct usb_endpoint_descriptor *
 +fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs,
 +              struct usb_endpoint_descriptor *hs)
 +{
 +      if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
 +              return hs;
 +      return fs;
 +}
 +
 +
 +/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */
 +static struct usb_string              fsg_strings[] = {
 +#ifndef FSG_NO_DEVICE_STRINGS
 +      {FSG_STRING_MANUFACTURER,       fsg_string_manufacturer},
 +      {FSG_STRING_PRODUCT,            fsg_string_product},
 +      {FSG_STRING_SERIAL,             fsg_string_serial},
 +      {FSG_STRING_CONFIG,             fsg_string_config},
 +#endif
 +      {FSG_STRING_INTERFACE,          fsg_string_interface},
 +      {}
 +};
 +
 +static struct usb_gadget_strings      fsg_stringtab = {
 +      .language       = 0x0409,               /* en-us */
 +      .strings        = fsg_strings,
 +};
 +
 +
 + /*-------------------------------------------------------------------------*/
 +
 +/*
 + * If the next two routines are called while the gadget is registered,
 + * the caller must own fsg->filesem for writing.
 + */
 +
 +static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
 +{
 +      int                             ro;
 +      struct file                     *filp = NULL;
 +      int                             rc = -EINVAL;
 +      struct inode                    *inode = NULL;
 +      loff_t                          size;
 +      loff_t                          num_sectors;
 +      loff_t                          min_sectors;
 +
 +      /* R/W if we can, R/O if we must */
 +      ro = curlun->initially_ro;
 +      if (!ro) {
 +              filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0);
 +              if (-EROFS == PTR_ERR(filp))
 +                      ro = 1;
 +      }
 +      if (ro)
 +              filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0);
 +      if (IS_ERR(filp)) {
 +              LINFO(curlun, "unable to open backing file: %s\n", filename);
 +              return PTR_ERR(filp);
 +      }
 +
 +      if (!(filp->f_mode & FMODE_WRITE))
 +              ro = 1;
 +
 +      if (filp->f_path.dentry)
 +              inode = filp->f_path.dentry->d_inode;
 +      if (inode && S_ISBLK(inode->i_mode)) {
 +              if (bdev_read_only(inode->i_bdev))
 +                      ro = 1;
 +      } else if (!inode || !S_ISREG(inode->i_mode)) {
 +              LINFO(curlun, "invalid file type: %s\n", filename);
 +              goto out;
 +      }
 +
 +      /*
 +       * If we can't read the file, it's no good.
 +       * If we can't write the file, use it read-only.
 +       */
 +      if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) {
 +              LINFO(curlun, "file not readable: %s\n", filename);
 +              goto out;
 +      }
 +      if (!(filp->f_op->write || filp->f_op->aio_write))
 +              ro = 1;
 +
 +      size = i_size_read(inode->i_mapping->host);
 +      if (size < 0) {
 +              LINFO(curlun, "unable to find file size: %s\n", filename);
 +              rc = (int) size;
 +              goto out;
 +      }
 +      num_sectors = size >> 9;        /* File size in 512-byte blocks */
 +      min_sectors = 1;
 +      if (curlun->cdrom) {
 +              num_sectors &= ~3;      /* Reduce to a multiple of 2048 */
 +              min_sectors = 300*4;    /* Smallest track is 300 frames */
 +              if (num_sectors >= 256*60*75*4) {
 +                      num_sectors = (256*60*75 - 1) * 4;
 +                      LINFO(curlun, "file too big: %s\n", filename);
 +                      LINFO(curlun, "using only first %d blocks\n",
 +                                      (int) num_sectors);
 +              }
 +      }
 +      if (num_sectors < min_sectors) {
 +              LINFO(curlun, "file too small: %s\n", filename);
 +              rc = -ETOOSMALL;
 +              goto out;
 +      }
 +
 +      get_file(filp);
 +      curlun->ro = ro;
 +      curlun->filp = filp;
 +      curlun->file_length = size;
 +      curlun->num_sectors = num_sectors;
 +      LDBG(curlun, "open backing file: %s\n", filename);
 +      rc = 0;
 +
 +out:
 +      filp_close(filp, current->files);
 +      return rc;
 +}
 +
 +
 +static void fsg_lun_close(struct fsg_lun *curlun)
 +{
 +      if (curlun->filp) {
 +              LDBG(curlun, "close backing file\n");
 +              fput(curlun->filp);
 +              curlun->filp = NULL;
 +      }
 +}
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +/*
 + * Sync the file data, don't bother with the metadata.
 + * This code was copied from fs/buffer.c:sys_fdatasync().
 + */
 +static int fsg_lun_fsync_sub(struct fsg_lun *curlun)
 +{
 +      struct file     *filp = curlun->filp;
 +
 +      if (curlun->ro || !filp)
 +              return 0;
 +      return vfs_fsync(filp, 1);
 +}
 +
 +static void store_cdrom_address(u8 *dest, int msf, u32 addr)
 +{
 +      if (msf) {
 +              /* Convert to Minutes-Seconds-Frames */
 +              addr >>= 2;             /* Convert to 2048-byte frames */
 +              addr += 2*75;           /* Lead-in occupies 2 seconds */
 +              dest[3] = addr % 75;    /* Frames */
 +              addr /= 75;
 +              dest[2] = addr % 60;    /* Seconds */
 +              addr /= 60;
 +              dest[1] = addr;         /* Minutes */
 +              dest[0] = 0;            /* Reserved */
 +      } else {
 +              /* Absolute sector */
 +              put_unaligned_be32(addr, dest);
 +      }
 +}
 +
 +
 +/*-------------------------------------------------------------------------*/
 +
 +
 +static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr,
 +                         char *buf)
 +{
 +      struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
 +
 +      return sprintf(buf, "%d\n", fsg_lun_is_open(curlun)
 +                                ? curlun->ro
 +                                : curlun->initially_ro);
 +}
 +
 +static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr,
 +                            char *buf)
 +{
 +      struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
 +
 +      return sprintf(buf, "%u\n", curlun->nofua);
 +}
 +
 +static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr,
 +                           char *buf)
 +{
 +      struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
 +      struct rw_semaphore     *filesem = dev_get_drvdata(dev);
 +      char            *p;
 +      ssize_t         rc;
 +
 +      down_read(filesem);
 +      if (fsg_lun_is_open(curlun)) {  /* Get the complete pathname */
 +              p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1);
 +              if (IS_ERR(p))
 +                      rc = PTR_ERR(p);
 +              else {
 +                      rc = strlen(p);
 +                      memmove(buf, p, rc);
 +                      buf[rc] = '\n';         /* Add a newline */
 +                      buf[++rc] = 0;
 +              }
 +      } else {                                /* No file, return 0 bytes */
 +              *buf = 0;
 +              rc = 0;
 +      }
 +      up_read(filesem);
 +      return rc;
 +}
 +
 +
 +static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr,
 +                          const char *buf, size_t count)
 +{
 +      ssize_t         rc = count;
 +      struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
 +      struct rw_semaphore     *filesem = dev_get_drvdata(dev);
 +      unsigned long   ro;
 +
 +      if (strict_strtoul(buf, 2, &ro))
 +              return -EINVAL;
 +
 +      /*
 +       * Allow the write-enable status to change only while the
 +       * backing file is closed.
 +       */
 +      down_read(filesem);
 +      if (fsg_lun_is_open(curlun)) {
 +              LDBG(curlun, "read-only status change prevented\n");
 +              rc = -EBUSY;
 +      } else {
 +              curlun->ro = ro;
 +              curlun->initially_ro = ro;
 +              LDBG(curlun, "read-only status set to %d\n", curlun->ro);
 +      }
 +      up_read(filesem);
 +      return rc;
 +}
 +
 +static ssize_t fsg_store_nofua(struct device *dev,
 +                             struct device_attribute *attr,
 +                             const char *buf, size_t count)
 +{
 +      struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
 +      unsigned long   nofua;
 +
 +      if (strict_strtoul(buf, 2, &nofua))
 +              return -EINVAL;
 +
 +      /* Sync data when switching from async mode to sync */
 +      if (!nofua && curlun->nofua)
 +              fsg_lun_fsync_sub(curlun);
 +
 +      curlun->nofua = nofua;
 +
 +      return count;
 +}
 +
 +static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr,
 +                            const char *buf, size_t count)
 +{
 +      struct fsg_lun  *curlun = fsg_lun_from_dev(dev);
 +      struct rw_semaphore     *filesem = dev_get_drvdata(dev);
 +      int             rc = 0;
 +
 +#ifdef CONFIG_ARCH_RK29
 +      printk("store_file: \"%s\"\n", buf);
 +#endif
 +
 +#ifndef CONFIG_USB_ANDROID_MASS_STORAGE
 +      /* disabled in android because we need to allow closing the backing file
 +       * if the media was removed
 +       */
 +      if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) {
 +              LDBG(curlun, "eject attempt prevented\n");
 +              return -EBUSY;                          /* "Door is locked" */
 +      }
 +#endif
 +
 +      /* Remove a trailing newline */
 +      if (count > 0 && buf[count-1] == '\n')
 +              ((char *) buf)[count-1] = 0;            /* Ugh! */
 +
 +      /* Eject current medium */
 +      down_write(filesem);
 +      if (fsg_lun_is_open(curlun)) {
 +              fsg_lun_close(curlun);
 +              curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT;
 +      }
 +
 +      /* Load new medium */
 +      if (count > 0 && buf[0]) {
 +              rc = fsg_lun_open(curlun, buf);
 +              if (rc == 0)
 +                      curlun->unit_attention_data =
 +                                      SS_NOT_READY_TO_READY_TRANSITION;
 +      }
 +      up_write(filesem);
 +      return (rc < 0 ? rc : count);
 +}
Simple merge
index 92067a302a70d8791595db3bd15fb7e65777ce53,b6c78fb583cf7d86979dafb2c696f23b044f4b1b..e36f6e21eb555974ee08dbabe388848de0ebaa3e
mode 100755,100644..100644
index 0d3a755c52c5a4e3681e3df167d0e7c69f33691a,2b3d83ba6a9cab0a4876bc0d4fb4208e9e46d393..75de541f4153680309c7e8390907b7668a096681
@@@ -203,9 -199,6 +203,12 @@@ struct mmc_host 
        const struct mmc_bus_ops *bus_ops;      /* current bus driver */
        unsigned int            bus_refs;       /* reference counter */
  
++#if defined(CONFIG_SDMMC_RK29) && !defined(CONFIG_SDMMC_RK29_OLD)
 +      unsigned int            re_initialized_flags; //in order to begin the rescan ;  added by xbw@2011-04-07
 +      unsigned int            doneflag; //added by xbw at 2011-08-27
++      int                     (*sdmmc_host_hw_init)(void *data);
++#endif
 +
        unsigned int            bus_resume_flags;
  #define MMC_BUSRESUME_MANUAL_RESUME   (1 << 0)
  #define MMC_BUSRESUME_NEEDS_RESUME    (1 << 1)
Simple merge
Simple merge
Simple merge
Simple merge