diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-14 15:29:14 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-14 15:29:14 -0400 |
| commit | 3ec2ab5514dbd6b5c4c3437c6a3cd9e5a90e84ef (patch) | |
| tree | 44225691130bac645c033db1f80cc083597f1bb3 | |
| parent | 200cfbb36ce360f7943c62b6c09885c215bfc1f5 (diff) | |
| parent | 90e07d9f54c61449dd48eff82e2354d0124d4f7e (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
pxamci: fix PXA27x MMC workaround for bad CRC with 136 bit response
mmc: use assigned major for block device
sdhci: handle dma boundary interrupts
mmc: au1xmmc command types check from data flags
| -rw-r--r-- | drivers/mmc/card/block.c | 17 | ||||
| -rw-r--r-- | drivers/mmc/host/au1xmmc.c | 35 | ||||
| -rw-r--r-- | drivers/mmc/host/pxamci.c | 18 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 9 | ||||
| -rw-r--r-- | include/linux/major.h | 2 |
5 files changed, 35 insertions, 46 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index d24ab234394c..a7562f7fc0b3 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
| @@ -45,8 +45,6 @@ | |||
| 45 | */ | 45 | */ |
| 46 | #define MMC_SHIFT 3 | 46 | #define MMC_SHIFT 3 |
| 47 | 47 | ||
| 48 | static int major; | ||
| 49 | |||
| 50 | /* | 48 | /* |
| 51 | * There is one mmc_blk_data per slot. | 49 | * There is one mmc_blk_data per slot. |
| 52 | */ | 50 | */ |
| @@ -466,7 +464,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
| 466 | md->queue.issue_fn = mmc_blk_issue_rq; | 464 | md->queue.issue_fn = mmc_blk_issue_rq; |
| 467 | md->queue.data = md; | 465 | md->queue.data = md; |
| 468 | 466 | ||
| 469 | md->disk->major = major; | 467 | md->disk->major = MMC_BLOCK_MAJOR; |
| 470 | md->disk->first_minor = devidx << MMC_SHIFT; | 468 | md->disk->first_minor = devidx << MMC_SHIFT; |
| 471 | md->disk->fops = &mmc_bdops; | 469 | md->disk->fops = &mmc_bdops; |
| 472 | md->disk->private_data = md; | 470 | md->disk->private_data = md; |
| @@ -634,14 +632,9 @@ static int __init mmc_blk_init(void) | |||
| 634 | { | 632 | { |
| 635 | int res = -ENOMEM; | 633 | int res = -ENOMEM; |
| 636 | 634 | ||
| 637 | res = register_blkdev(major, "mmc"); | 635 | res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); |
| 638 | if (res < 0) { | 636 | if (res) |
| 639 | printk(KERN_WARNING "Unable to get major %d for MMC media: %d\n", | ||
| 640 | major, res); | ||
| 641 | goto out; | 637 | goto out; |
| 642 | } | ||
| 643 | if (major == 0) | ||
| 644 | major = res; | ||
| 645 | 638 | ||
| 646 | return mmc_register_driver(&mmc_driver); | 639 | return mmc_register_driver(&mmc_driver); |
| 647 | 640 | ||
| @@ -652,7 +645,7 @@ static int __init mmc_blk_init(void) | |||
| 652 | static void __exit mmc_blk_exit(void) | 645 | static void __exit mmc_blk_exit(void) |
| 653 | { | 646 | { |
| 654 | mmc_unregister_driver(&mmc_driver); | 647 | mmc_unregister_driver(&mmc_driver); |
| 655 | unregister_blkdev(major, "mmc"); | 648 | unregister_blkdev(MMC_BLOCK_MAJOR, "mmc"); |
| 656 | } | 649 | } |
| 657 | 650 | ||
| 658 | module_init(mmc_blk_init); | 651 | module_init(mmc_blk_init); |
| @@ -661,5 +654,3 @@ module_exit(mmc_blk_exit); | |||
| 661 | MODULE_LICENSE("GPL"); | 654 | MODULE_LICENSE("GPL"); |
| 662 | MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver"); | 655 | MODULE_DESCRIPTION("Multimedia Card (MMC) block device driver"); |
| 663 | 656 | ||
| 664 | module_param(major, int, 0444); | ||
| 665 | MODULE_PARM_DESC(major, "specify the major device number for MMC block driver"); | ||
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index b7156a4555b5..f967226d7505 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c | |||
| @@ -187,9 +187,8 @@ static void au1xmmc_tasklet_finish(unsigned long param) | |||
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, | 189 | static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, |
| 190 | struct mmc_command *cmd) | 190 | struct mmc_command *cmd, unsigned int flags) |
| 191 | { | 191 | { |
| 192 | |||
| 193 | u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); | 192 | u32 mmccmd = (cmd->opcode << SD_CMD_CI_SHIFT); |
| 194 | 193 | ||
| 195 | switch (mmc_resp_type(cmd)) { | 194 | switch (mmc_resp_type(cmd)) { |
| @@ -213,24 +212,16 @@ static int au1xmmc_send_command(struct au1xmmc_host *host, int wait, | |||
| 213 | return MMC_ERR_INVALID; | 212 | return MMC_ERR_INVALID; |
| 214 | } | 213 | } |
| 215 | 214 | ||
| 216 | switch(cmd->opcode) { | 215 | if (flags & MMC_DATA_READ) { |
| 217 | case MMC_READ_SINGLE_BLOCK: | 216 | if (flags & MMC_DATA_MULTI) |
| 218 | case SD_APP_SEND_SCR: | 217 | mmccmd |= SD_CMD_CT_4; |
| 219 | mmccmd |= SD_CMD_CT_2; | 218 | else |
| 220 | break; | 219 | mmccmd |= SD_CMD_CT_2; |
| 221 | case MMC_READ_MULTIPLE_BLOCK: | 220 | } else if (flags & MMC_DATA_WRITE) { |
| 222 | mmccmd |= SD_CMD_CT_4; | 221 | if (flags & MMC_DATA_MULTI) |
| 223 | break; | 222 | mmccmd |= SD_CMD_CT_3; |
| 224 | case MMC_WRITE_BLOCK: | 223 | else |
| 225 | mmccmd |= SD_CMD_CT_1; | 224 | mmccmd |= SD_CMD_CT_1; |
| 226 | break; | ||
| 227 | |||
| 228 | case MMC_WRITE_MULTIPLE_BLOCK: | ||
| 229 | mmccmd |= SD_CMD_CT_3; | ||
| 230 | break; | ||
| 231 | case MMC_STOP_TRANSMISSION: | ||
| 232 | mmccmd |= SD_CMD_CT_7; | ||
| 233 | break; | ||
| 234 | } | 225 | } |
| 235 | 226 | ||
| 236 | au_writel(cmd->arg, HOST_CMDARG(host)); | 227 | au_writel(cmd->arg, HOST_CMDARG(host)); |
| @@ -665,6 +656,7 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq) | |||
| 665 | { | 656 | { |
| 666 | 657 | ||
| 667 | struct au1xmmc_host *host = mmc_priv(mmc); | 658 | struct au1xmmc_host *host = mmc_priv(mmc); |
| 659 | unsigned int flags = 0; | ||
| 668 | int ret = MMC_ERR_NONE; | 660 | int ret = MMC_ERR_NONE; |
| 669 | 661 | ||
| 670 | WARN_ON(irqs_disabled()); | 662 | WARN_ON(irqs_disabled()); |
| @@ -677,11 +669,12 @@ static void au1xmmc_request(struct mmc_host* mmc, struct mmc_request* mrq) | |||
| 677 | 669 | ||
| 678 | if (mrq->data) { | 670 | if (mrq->data) { |
| 679 | FLUSH_FIFO(host); | 671 | FLUSH_FIFO(host); |
| 672 | flags = mrq->data->flags; | ||
| 680 | ret = au1xmmc_prepare_data(host, mrq->data); | 673 | ret = au1xmmc_prepare_data(host, mrq->data); |
| 681 | } | 674 | } |
| 682 | 675 | ||
| 683 | if (ret == MMC_ERR_NONE) | 676 | if (ret == MMC_ERR_NONE) |
| 684 | ret = au1xmmc_send_command(host, 0, mrq->cmd); | 677 | ret = au1xmmc_send_command(host, 0, mrq->cmd, flags); |
| 685 | 678 | ||
| 686 | if (ret != MMC_ERR_NONE) { | 679 | if (ret != MMC_ERR_NONE) { |
| 687 | mrq->cmd->error = ret; | 680 | mrq->cmd->error = ret; |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index d97d3864b57f..f8985c508bb9 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
| @@ -232,20 +232,14 @@ static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) | |||
| 232 | /* | 232 | /* |
| 233 | * workaround for erratum #42: | 233 | * workaround for erratum #42: |
| 234 | * Intel PXA27x Family Processor Specification Update Rev 001 | 234 | * Intel PXA27x Family Processor Specification Update Rev 001 |
| 235 | * A bogus CRC error can appear if the msb of a 136 bit | ||
| 236 | * response is a one. | ||
| 235 | */ | 237 | */ |
| 236 | if (cmd->opcode == MMC_ALL_SEND_CID || | 238 | if (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000) { |
| 237 | cmd->opcode == MMC_SEND_CSD || | 239 | pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode); |
| 238 | cmd->opcode == MMC_SEND_CID) { | 240 | } else |
| 239 | /* a bogus CRC error can appear if the msb of | ||
| 240 | the 15 byte response is a one */ | ||
| 241 | if ((cmd->resp[0] & 0x80000000) == 0) | ||
| 242 | cmd->error = MMC_ERR_BADCRC; | ||
| 243 | } else { | ||
| 244 | pr_debug("ignoring CRC from command %d - *risky*\n",cmd->opcode); | ||
| 245 | } | ||
| 246 | #else | ||
| 247 | cmd->error = MMC_ERR_BADCRC; | ||
| 248 | #endif | 241 | #endif |
| 242 | cmd->error = MMC_ERR_BADCRC; | ||
| 249 | } | 243 | } |
| 250 | 244 | ||
| 251 | pxamci_disable_irq(host, END_CMD_RES); | 245 | pxamci_disable_irq(host, END_CMD_RES); |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ff5bf73cdd25..a359efdd77eb 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -963,6 +963,15 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
| 963 | if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) | 963 | if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)) |
| 964 | sdhci_transfer_pio(host); | 964 | sdhci_transfer_pio(host); |
| 965 | 965 | ||
| 966 | /* | ||
| 967 | * We currently don't do anything fancy with DMA | ||
| 968 | * boundaries, but as we can't disable the feature | ||
| 969 | * we need to at least restart the transfer. | ||
| 970 | */ | ||
| 971 | if (intmask & SDHCI_INT_DMA_END) | ||
| 972 | writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS), | ||
| 973 | host->ioaddr + SDHCI_DMA_ADDRESS); | ||
| 974 | |||
| 966 | if (intmask & SDHCI_INT_DATA_END) | 975 | if (intmask & SDHCI_INT_DATA_END) |
| 967 | sdhci_finish_data(host); | 976 | sdhci_finish_data(host); |
| 968 | } | 977 | } |
diff --git a/include/linux/major.h b/include/linux/major.h index 0a74c52924c9..7e7c9093919a 100644 --- a/include/linux/major.h +++ b/include/linux/major.h | |||
| @@ -152,6 +152,8 @@ | |||
| 152 | #define USB_ACM_AUX_MAJOR 167 | 152 | #define USB_ACM_AUX_MAJOR 167 |
| 153 | #define USB_CHAR_MAJOR 180 | 153 | #define USB_CHAR_MAJOR 180 |
| 154 | 154 | ||
| 155 | #define MMC_BLOCK_MAJOR 179 | ||
| 156 | |||
| 155 | #define VXVM_MAJOR 199 /* VERITAS volume i/o driver */ | 157 | #define VXVM_MAJOR 199 /* VERITAS volume i/o driver */ |
| 156 | #define VXSPEC_MAJOR 200 /* VERITAS volume config driver */ | 158 | #define VXSPEC_MAJOR 200 /* VERITAS volume config driver */ |
| 157 | #define VXDMP_MAJOR 201 /* VERITAS volume multipath driver */ | 159 | #define VXDMP_MAJOR 201 /* VERITAS volume multipath driver */ |
