[Bluetooth] Correct SCO buffer for another Broadcom based dongle
[sfrench/cifs-2.6.git] / drivers / mmc / mmc.c
index 9d190022a4905f8d3682699ab2c87ec67e693ff6..4a73e8b2428d8e3d61f21c1bcc990aa23ce4f976 100644 (file)
@@ -103,11 +103,16 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
                 mmc_hostname(host), mrq->cmd->opcode,
                 mrq->cmd->arg, mrq->cmd->flags);
 
-       WARN_ON(host->card_busy == NULL);
+       WARN_ON(!host->claimed);
 
        mrq->cmd->error = 0;
        mrq->cmd->mrq = mrq;
        if (mrq->data) {
+               BUG_ON(mrq->data->blksz > host->max_blk_size);
+               BUG_ON(mrq->data->blocks > host->max_blk_count);
+               BUG_ON(mrq->data->blocks * mrq->data->blksz >
+                       host->max_req_size);
+
                mrq->cmd->data = mrq->data;
                mrq->data->error = 0;
                mrq->data->mrq = mrq;
@@ -157,7 +162,7 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries
 {
        struct mmc_request mrq;
 
-       BUG_ON(host->card_busy == NULL);
+       BUG_ON(!host->claimed);
 
        memset(&mrq, 0, sizeof(struct mmc_request));
 
@@ -195,7 +200,7 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, unsigned int rca,
 
        int i, err;
 
-       BUG_ON(host->card_busy == NULL);
+       BUG_ON(!host->claimed);
        BUG_ON(retries < 0);
 
        err = MMC_ERR_INVALID;
@@ -289,7 +294,10 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card,
                else
                        limit_us = 100000;
 
-               if (timeout_us > limit_us) {
+               /*
+                * SDHC cards always use these fixed values.
+                */
+               if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
                        data->timeout_ns = limit_us * 1000;
                        data->timeout_clks = 0;
                }
@@ -320,14 +328,14 @@ int __mmc_claim_host(struct mmc_host *host, struct mmc_card *card)
        spin_lock_irqsave(&host->lock, flags);
        while (1) {
                set_current_state(TASK_UNINTERRUPTIBLE);
-               if (host->card_busy == NULL)
+               if (!host->claimed)
                        break;
                spin_unlock_irqrestore(&host->lock, flags);
                schedule();
                spin_lock_irqsave(&host->lock, flags);
        }
        set_current_state(TASK_RUNNING);
-       host->card_busy = card;
+       host->claimed = 1;
        spin_unlock_irqrestore(&host->lock, flags);
        remove_wait_queue(&host->wq, &wait);
 
@@ -353,10 +361,10 @@ void mmc_release_host(struct mmc_host *host)
 {
        unsigned long flags;
 
-       BUG_ON(host->card_busy == NULL);
+       BUG_ON(!host->claimed);
 
        spin_lock_irqsave(&host->lock, flags);
-       host->card_busy = NULL;
+       host->claimed = 0;
        spin_unlock_irqrestore(&host->lock, flags);
 
        wake_up(&host->wq);
@@ -368,11 +376,12 @@ static inline void mmc_set_ios(struct mmc_host *host)
 {
        struct mmc_ios *ios = &host->ios;
 
-       pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u width %u\n",
+       pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
+               "width %u timing %u\n",
                 mmc_hostname(host), ios->clock, ios->bus_mode,
                 ios->power_mode, ios->chip_select, ios->vdd,
-                ios->bus_width);
-       
+                ios->bus_width, ios->timing);
+
        host->ops->set_ios(host, ios);
 }
 
@@ -381,7 +390,7 @@ static int mmc_select_card(struct mmc_host *host, struct mmc_card *card)
        int err;
        struct mmc_command cmd;
 
-       BUG_ON(host->card_busy == NULL);
+       BUG_ON(!host->claimed);
 
        if (host->card_selected == card)
                return MMC_ERR_NONE;
@@ -588,34 +597,65 @@ static void mmc_decode_csd(struct mmc_card *card)
 
        if (mmc_card_sd(card)) {
                csd_struct = UNSTUFF_BITS(resp, 126, 2);
-               if (csd_struct != 0) {
+
+               switch (csd_struct) {
+               case 0:
+                       m = UNSTUFF_BITS(resp, 115, 4);
+                       e = UNSTUFF_BITS(resp, 112, 3);
+                       csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
+                       csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
+
+                       m = UNSTUFF_BITS(resp, 99, 4);
+                       e = UNSTUFF_BITS(resp, 96, 3);
+                       csd->max_dtr      = tran_exp[e] * tran_mant[m];
+                       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+                       e = UNSTUFF_BITS(resp, 47, 3);
+                       m = UNSTUFF_BITS(resp, 62, 12);
+                       csd->capacity     = (1 + m) << (e + 2);
+
+                       csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
+                       csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
+                       csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
+                       csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
+                       csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
+                       csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
+                       csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
+                       break;
+               case 1:
+                       /*
+                        * This is a block-addressed SDHC card. Most
+                        * interesting fields are unused and have fixed
+                        * values. To avoid getting tripped by buggy cards,
+                        * we assume those fixed values ourselves.
+                        */
+                       mmc_card_set_blockaddr(card);
+
+                       csd->tacc_ns     = 0; /* Unused */
+                       csd->tacc_clks   = 0; /* Unused */
+
+                       m = UNSTUFF_BITS(resp, 99, 4);
+                       e = UNSTUFF_BITS(resp, 96, 3);
+                       csd->max_dtr      = tran_exp[e] * tran_mant[m];
+                       csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
+
+                       m = UNSTUFF_BITS(resp, 48, 22);
+                       csd->capacity     = (1 + m) << 10;
+
+                       csd->read_blkbits = 9;
+                       csd->read_partial = 0;
+                       csd->write_misalign = 0;
+                       csd->read_misalign = 0;
+                       csd->r2w_factor = 4; /* Unused */
+                       csd->write_blkbits = 9;
+                       csd->write_partial = 0;
+                       break;
+               default:
                        printk("%s: unrecognised CSD structure version %d\n",
                                mmc_hostname(card->host), csd_struct);
                        mmc_card_set_bad(card);
                        return;
                }
-
-               m = UNSTUFF_BITS(resp, 115, 4);
-               e = UNSTUFF_BITS(resp, 112, 3);
-               csd->tacc_ns     = (tacc_exp[e] * tacc_mant[m] + 9) / 10;
-               csd->tacc_clks   = UNSTUFF_BITS(resp, 104, 8) * 100;
-
-               m = UNSTUFF_BITS(resp, 99, 4);
-               e = UNSTUFF_BITS(resp, 96, 3);
-               csd->max_dtr      = tran_exp[e] * tran_mant[m];
-               csd->cmdclass     = UNSTUFF_BITS(resp, 84, 12);
-
-               e = UNSTUFF_BITS(resp, 47, 3);
-               m = UNSTUFF_BITS(resp, 62, 12);
-               csd->capacity     = (1 + m) << (e + 2);
-
-               csd->read_blkbits = UNSTUFF_BITS(resp, 80, 4);
-               csd->read_partial = UNSTUFF_BITS(resp, 79, 1);
-               csd->write_misalign = UNSTUFF_BITS(resp, 78, 1);
-               csd->read_misalign = UNSTUFF_BITS(resp, 77, 1);
-               csd->r2w_factor = UNSTUFF_BITS(resp, 26, 3);
-               csd->write_blkbits = UNSTUFF_BITS(resp, 22, 4);
-               csd->write_partial = UNSTUFF_BITS(resp, 21, 1);
        } else {
                /*
                 * We only understand CSD structure v1.1 and v1.2.
@@ -770,6 +810,7 @@ static void mmc_power_up(struct mmc_host *host)
        host->ios.chip_select = MMC_CS_DONTCARE;
        host->ios.power_mode = MMC_POWER_UP;
        host->ios.bus_width = MMC_BUS_WIDTH_1;
+       host->ios.timing = MMC_TIMING_LEGACY;
        mmc_set_ios(host);
 
        mmc_delay(1);
@@ -789,6 +830,7 @@ static void mmc_power_off(struct mmc_host *host)
        host->ios.chip_select = MMC_CS_DONTCARE;
        host->ios.power_mode = MMC_POWER_OFF;
        host->ios.bus_width = MMC_BUS_WIDTH_1;
+       host->ios.timing = MMC_TIMING_LEGACY;
        mmc_set_ios(host);
 }
 
@@ -848,6 +890,41 @@ static int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
        return err;
 }
 
+static int mmc_send_if_cond(struct mmc_host *host, u32 ocr, int *rsd2)
+{
+       struct mmc_command cmd;
+       int err, sd2;
+       static const u8 test_pattern = 0xAA;
+
+       /*
+       * To support SD 2.0 cards, we must always invoke SD_SEND_IF_COND
+       * before SD_APP_OP_COND. This command will harmlessly fail for
+       * SD 1.0 cards.
+       */
+       cmd.opcode = SD_SEND_IF_COND;
+       cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
+       cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
+
+       err = mmc_wait_for_cmd(host, &cmd, 0);
+       if (err == MMC_ERR_NONE) {
+               if ((cmd.resp[0] & 0xFF) == test_pattern) {
+                       sd2 = 1;
+               } else {
+                       sd2 = 0;
+                       err = MMC_ERR_FAILED;
+               }
+       } else {
+               /*
+                * Treat errors as SD 1.0 card.
+                */
+               sd2 = 0;
+               err = MMC_ERR_NONE;
+       }
+       if (rsd2)
+               *rsd2 = sd2;
+       return err;
+}
+
 /*
  * Discover cards by requesting their CID.  If this command
  * times out, it is not an error; there are no further cards
@@ -1018,7 +1095,8 @@ static void mmc_process_ext_csds(struct mmc_host *host)
                mmc_wait_for_req(host, &mrq);
 
                if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
+                       printk("%s: unable to read EXT_CSD, performance "
+                               "might suffer.\n", mmc_hostname(card->host));
                        continue;
                }
 
@@ -1034,50 +1112,53 @@ static void mmc_process_ext_csds(struct mmc_host *host)
                        printk("%s: card is mmc v4 but doesn't support "
                               "any high-speed modes.\n",
                                mmc_hostname(card->host));
-                       mmc_card_set_bad(card);
                        continue;
                }
 
-               /* Activate highspeed support. */
-               cmd.opcode = MMC_SWITCH;
-               cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                         (EXT_CSD_HS_TIMING << 16) |
-                         (1 << 8) |
-                         EXT_CSD_CMD_SET_NORMAL;
-               cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+               if (host->caps & MMC_CAP_MMC_HIGHSPEED) {
+                       /* Activate highspeed support. */
+                       cmd.opcode = MMC_SWITCH;
+                       cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                                 (EXT_CSD_HS_TIMING << 16) |
+                                 (1 << 8) |
+                                 EXT_CSD_CMD_SET_NORMAL;
+                       cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
 
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-               if (err != MMC_ERR_NONE) {
-                       printk("%s: failed to switch card to mmc v4 "
-                              "high-speed mode.\n",
-                              mmc_hostname(card->host));
-                       continue;
-               }
+                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+                       if (err != MMC_ERR_NONE) {
+                               printk("%s: failed to switch card to mmc v4 "
+                                      "high-speed mode.\n",
+                                      mmc_hostname(card->host));
+                               continue;
+                       }
 
-               mmc_card_set_highspeed(card);
+                       mmc_card_set_highspeed(card);
 
-               /* Check for host support for wide-bus modes. */
-               if (!(host->caps & MMC_CAP_4_BIT_DATA)) {
-                       continue;
+                       host->ios.timing = MMC_TIMING_SD_HS;
+                       mmc_set_ios(host);
                }
 
-               /* Activate 4-bit support. */
-               cmd.opcode = MMC_SWITCH;
-               cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
-                         (EXT_CSD_BUS_WIDTH << 16) |
-                         (EXT_CSD_BUS_WIDTH_4 << 8) |
-                         EXT_CSD_CMD_SET_NORMAL;
-               cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
+               /* Check for host support for wide-bus modes. */
+               if (host->caps & MMC_CAP_4_BIT_DATA) {
+                       /* Activate 4-bit support. */
+                       cmd.opcode = MMC_SWITCH;
+                       cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
+                                 (EXT_CSD_BUS_WIDTH << 16) |
+                                 (EXT_CSD_BUS_WIDTH_4 << 8) |
+                                 EXT_CSD_CMD_SET_NORMAL;
+                       cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
 
-               err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
-               if (err != MMC_ERR_NONE) {
-                       printk("%s: failed to switch card to "
-                              "mmc v4 4-bit bus mode.\n",
-                              mmc_hostname(card->host));
-                       continue;
-               }
+                       err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES);
+                       if (err != MMC_ERR_NONE) {
+                               printk("%s: failed to switch card to "
+                                      "mmc v4 4-bit bus mode.\n",
+                                      mmc_hostname(card->host));
+                               continue;
+                       }
 
-               host->ios.bus_width = MMC_BUS_WIDTH_4;
+                       host->ios.bus_width = MMC_BUS_WIDTH_4;
+                       mmc_set_ios(host);
+               }
        }
 
        kfree(ext_csd);
@@ -1167,6 +1248,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
        unsigned char *status;
        struct scatterlist sg;
 
+       if (!(host->caps & MMC_CAP_SD_HIGHSPEED))
+               return;
+
        status = kmalloc(64, GFP_KERNEL);
        if (!status) {
                printk(KERN_WARNING "%s: Unable to allocate buffer for "
@@ -1215,7 +1299,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
                mmc_wait_for_req(host, &mrq);
 
                if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
+                       printk("%s: unable to read switch capabilities, "
+                               "performance might suffer.\n",
+                               mmc_hostname(card->host));
                        continue;
                }
 
@@ -1247,12 +1333,8 @@ static void mmc_read_switch_caps(struct mmc_host *host)
 
                mmc_wait_for_req(host, &mrq);
 
-               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE) {
-                       mmc_card_set_dead(card);
-                       continue;
-               }
-
-               if ((status[16] & 0xF) != 1) {
+               if (cmd.error != MMC_ERR_NONE || data.error != MMC_ERR_NONE ||
+                       (status[16] & 0xF) != 1) {
                        printk(KERN_WARNING "%s: Problem switching card "
                                "into high-speed mode!\n",
                                mmc_hostname(host));
@@ -1260,6 +1342,9 @@ static void mmc_read_switch_caps(struct mmc_host *host)
                }
 
                mmc_card_set_highspeed(card);
+
+               host->ios.timing = MMC_TIMING_SD_HS;
+               mmc_set_ios(host);
        }
 
        kfree(status);
@@ -1334,6 +1419,10 @@ static void mmc_setup(struct mmc_host *host)
                mmc_power_up(host);
                mmc_idle_cards(host);
 
+               err = mmc_send_if_cond(host, host->ocr_avail, NULL);
+               if (err != MMC_ERR_NONE) {
+                       return;
+               }
                err = mmc_send_app_op_cond(host, 0, &ocr);
 
                /*
@@ -1386,10 +1475,21 @@ static void mmc_setup(struct mmc_host *host)
         * all get the idea that they should be ready for CMD2.
         * (My SanDisk card seems to need this.)
         */
-       if (host->mode == MMC_MODE_SD)
-               mmc_send_app_op_cond(host, host->ocr, NULL);
-       else
+       if (host->mode == MMC_MODE_SD) {
+               int err, sd2;
+               err = mmc_send_if_cond(host, host->ocr, &sd2);
+               if (err == MMC_ERR_NONE) {
+                       /*
+                       * If SD_SEND_IF_COND indicates an SD 2.0
+                       * compliant card and we should set bit 30
+                       * of the ocr to indicate that we can handle
+                       * block-addressed SDHC cards.
+                       */
+                       mmc_send_app_op_cond(host, host->ocr | (sd2 << 30), NULL);
+               }
+       } else {
                mmc_send_op_cond(host, host->ocr, NULL);
+       }
 
        mmc_discover_cards(host);
 
@@ -1419,18 +1519,16 @@ static void mmc_setup(struct mmc_host *host)
  */
 void mmc_detect_change(struct mmc_host *host, unsigned long delay)
 {
-       if (delay)
-               mmc_schedule_delayed_work(&host->detect, delay);
-       else
-               mmc_schedule_work(&host->detect);
+       mmc_schedule_delayed_work(&host->detect, delay);
 }
 
 EXPORT_SYMBOL(mmc_detect_change);
 
 
-static void mmc_rescan(void *data)
+static void mmc_rescan(struct work_struct *work)
 {
-       struct mmc_host *host = data;
+       struct mmc_host *host =
+               container_of(work, struct mmc_host, detect.work);
        struct list_head *l, *n;
        unsigned char power_mode;
 
@@ -1513,7 +1611,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
                spin_lock_init(&host->lock);
                init_waitqueue_head(&host->wq);
                INIT_LIST_HEAD(&host->cards);
-               INIT_WORK(&host->detect, mmc_rescan, host);
+               INIT_DELAYED_WORK(&host->detect, mmc_rescan);
 
                /*
                 * By default, hosts do not support SGIO or large requests.
@@ -1521,8 +1619,11 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
                 */
                host->max_hw_segs = 1;
                host->max_phys_segs = 1;
-               host->max_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
                host->max_seg_size = PAGE_CACHE_SIZE;
+
+               host->max_req_size = PAGE_CACHE_SIZE;
+               host->max_blk_size = 512;
+               host->max_blk_count = PAGE_CACHE_SIZE / 512;
        }
 
        return host;
@@ -1611,7 +1712,7 @@ EXPORT_SYMBOL(mmc_suspend_host);
  */
 int mmc_resume_host(struct mmc_host *host)
 {
-       mmc_rescan(host);
+       mmc_rescan(&host->detect.work);
 
        return 0;
 }