diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/mmc/card/block.c | 17 | ||||
| -rw-r--r-- | drivers/mmc/card/mmc_test.c | 85 | ||||
| -rw-r--r-- | drivers/mmc/core/core.c | 5 | ||||
| -rw-r--r-- | drivers/mmc/host/au1xmmc.c | 8 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 3 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.c | 15 | ||||
| -rw-r--r-- | drivers/mmc/host/sdhci.h | 2 |
7 files changed, 40 insertions, 95 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 66e5a5487c2..86dbb366415 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
| @@ -213,7 +213,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 213 | struct mmc_blk_data *md = mq->data; | 213 | struct mmc_blk_data *md = mq->data; |
| 214 | struct mmc_card *card = md->queue.card; | 214 | struct mmc_card *card = md->queue.card; |
| 215 | struct mmc_blk_request brq; | 215 | struct mmc_blk_request brq; |
| 216 | int ret = 1, sg_pos, data_size; | 216 | int ret = 1, data_size, i; |
| 217 | struct scatterlist *sg; | ||
| 217 | 218 | ||
| 218 | mmc_claim_host(card->host); | 219 | mmc_claim_host(card->host); |
| 219 | 220 | ||
| @@ -267,18 +268,22 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 267 | 268 | ||
| 268 | mmc_queue_bounce_pre(mq); | 269 | mmc_queue_bounce_pre(mq); |
| 269 | 270 | ||
| 271 | /* | ||
| 272 | * Adjust the sg list so it is the same size as the | ||
| 273 | * request. | ||
| 274 | */ | ||
| 270 | if (brq.data.blocks != | 275 | if (brq.data.blocks != |
| 271 | (req->nr_sectors >> (md->block_bits - 9))) { | 276 | (req->nr_sectors >> (md->block_bits - 9))) { |
| 272 | data_size = brq.data.blocks * brq.data.blksz; | 277 | data_size = brq.data.blocks * brq.data.blksz; |
| 273 | for (sg_pos = 0; sg_pos < brq.data.sg_len; sg_pos++) { | 278 | for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) { |
| 274 | data_size -= mq->sg[sg_pos].length; | 279 | data_size -= sg->length; |
| 275 | if (data_size <= 0) { | 280 | if (data_size <= 0) { |
| 276 | mq->sg[sg_pos].length += data_size; | 281 | sg->length += data_size; |
| 277 | sg_pos++; | 282 | i++; |
| 278 | break; | 283 | break; |
| 279 | } | 284 | } |
| 280 | } | 285 | } |
| 281 | brq.data.sg_len = sg_pos; | 286 | brq.data.sg_len = i; |
| 282 | } | 287 | } |
| 283 | 288 | ||
| 284 | mmc_wait_for_req(card->host, &brq.mrq); | 289 | mmc_wait_for_req(card->host, &brq.mrq); |
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index a067fe43630..f26b01d811a 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c | |||
| @@ -388,16 +388,14 @@ static int mmc_test_transfer(struct mmc_test_card *test, | |||
| 388 | int ret, i; | 388 | int ret, i; |
| 389 | unsigned long flags; | 389 | unsigned long flags; |
| 390 | 390 | ||
| 391 | BUG_ON(blocks * blksz > BUFFER_SIZE); | ||
| 392 | |||
| 393 | if (write) { | 391 | if (write) { |
| 394 | for (i = 0;i < blocks * blksz;i++) | 392 | for (i = 0;i < blocks * blksz;i++) |
| 395 | test->scratch[i] = i; | 393 | test->scratch[i] = i; |
| 396 | } else { | 394 | } else { |
| 397 | memset(test->scratch, 0, blocks * blksz); | 395 | memset(test->scratch, 0, BUFFER_SIZE); |
| 398 | } | 396 | } |
| 399 | local_irq_save(flags); | 397 | local_irq_save(flags); |
| 400 | sg_copy_from_buffer(sg, sg_len, test->scratch, blocks * blksz); | 398 | sg_copy_from_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); |
| 401 | local_irq_restore(flags); | 399 | local_irq_restore(flags); |
| 402 | 400 | ||
| 403 | ret = mmc_test_set_blksize(test, blksz); | 401 | ret = mmc_test_set_blksize(test, blksz); |
| @@ -444,7 +442,7 @@ static int mmc_test_transfer(struct mmc_test_card *test, | |||
| 444 | } | 442 | } |
| 445 | } else { | 443 | } else { |
| 446 | local_irq_save(flags); | 444 | local_irq_save(flags); |
| 447 | sg_copy_to_buffer(sg, sg_len, test->scratch, blocks * blksz); | 445 | sg_copy_to_buffer(sg, sg_len, test->scratch, BUFFER_SIZE); |
| 448 | local_irq_restore(flags); | 446 | local_irq_restore(flags); |
| 449 | for (i = 0;i < blocks * blksz;i++) { | 447 | for (i = 0;i < blocks * blksz;i++) { |
| 450 | if (test->scratch[i] != (u8)i) | 448 | if (test->scratch[i] != (u8)i) |
| @@ -805,69 +803,6 @@ static int mmc_test_multi_xfersize_read(struct mmc_test_card *test) | |||
| 805 | return 0; | 803 | return 0; |
| 806 | } | 804 | } |
| 807 | 805 | ||
| 808 | static int mmc_test_bigsg_write(struct mmc_test_card *test) | ||
| 809 | { | ||
| 810 | int ret; | ||
| 811 | unsigned int size; | ||
| 812 | struct scatterlist sg; | ||
| 813 | |||
| 814 | if (test->card->host->max_blk_count == 1) | ||
| 815 | return RESULT_UNSUP_HOST; | ||
| 816 | |||
| 817 | size = PAGE_SIZE * 2; | ||
| 818 | size = min(size, test->card->host->max_req_size); | ||
| 819 | size = min(size, test->card->host->max_seg_size); | ||
| 820 | size = min(size, test->card->host->max_blk_count * 512); | ||
| 821 | |||
| 822 | memset(test->buffer, 0, BUFFER_SIZE); | ||
| 823 | |||
| 824 | if (size < 1024) | ||
| 825 | return RESULT_UNSUP_HOST; | ||
| 826 | |||
| 827 | sg_init_table(&sg, 1); | ||
| 828 | sg_init_one(&sg, test->buffer, BUFFER_SIZE); | ||
| 829 | |||
| 830 | ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 1); | ||
| 831 | if (ret) | ||
| 832 | return ret; | ||
| 833 | |||
| 834 | return 0; | ||
| 835 | } | ||
| 836 | |||
| 837 | static int mmc_test_bigsg_read(struct mmc_test_card *test) | ||
| 838 | { | ||
| 839 | int ret, i; | ||
| 840 | unsigned int size; | ||
| 841 | struct scatterlist sg; | ||
| 842 | |||
| 843 | if (test->card->host->max_blk_count == 1) | ||
| 844 | return RESULT_UNSUP_HOST; | ||
| 845 | |||
| 846 | size = PAGE_SIZE * 2; | ||
| 847 | size = min(size, test->card->host->max_req_size); | ||
| 848 | size = min(size, test->card->host->max_seg_size); | ||
| 849 | size = min(size, test->card->host->max_blk_count * 512); | ||
| 850 | |||
| 851 | if (size < 1024) | ||
| 852 | return RESULT_UNSUP_HOST; | ||
| 853 | |||
| 854 | memset(test->buffer, 0xCD, BUFFER_SIZE); | ||
| 855 | |||
| 856 | sg_init_table(&sg, 1); | ||
| 857 | sg_init_one(&sg, test->buffer, BUFFER_SIZE); | ||
| 858 | ret = mmc_test_transfer(test, &sg, 1, 0, size/512, 512, 0); | ||
| 859 | if (ret) | ||
| 860 | return ret; | ||
| 861 | |||
| 862 | /* mmc_test_transfer() doesn't check for read overflows */ | ||
| 863 | for (i = size;i < BUFFER_SIZE;i++) { | ||
| 864 | if (test->buffer[i] != 0xCD) | ||
| 865 | return RESULT_FAIL; | ||
| 866 | } | ||
| 867 | |||
| 868 | return 0; | ||
| 869 | } | ||
| 870 | |||
| 871 | #ifdef CONFIG_HIGHMEM | 806 | #ifdef CONFIG_HIGHMEM |
| 872 | 807 | ||
| 873 | static int mmc_test_write_high(struct mmc_test_card *test) | 808 | static int mmc_test_write_high(struct mmc_test_card *test) |
| @@ -1071,20 +1006,6 @@ static const struct mmc_test_case mmc_test_cases[] = { | |||
| 1071 | .run = mmc_test_multi_xfersize_read, | 1006 | .run = mmc_test_multi_xfersize_read, |
| 1072 | }, | 1007 | }, |
| 1073 | 1008 | ||
| 1074 | { | ||
| 1075 | .name = "Over-sized SG list write", | ||
| 1076 | .prepare = mmc_test_prepare_write, | ||
| 1077 | .run = mmc_test_bigsg_write, | ||
| 1078 | .cleanup = mmc_test_cleanup, | ||
| 1079 | }, | ||
| 1080 | |||
| 1081 | { | ||
| 1082 | .name = "Over-sized SG list read", | ||
| 1083 | .prepare = mmc_test_prepare_read, | ||
| 1084 | .run = mmc_test_bigsg_read, | ||
| 1085 | .cleanup = mmc_test_cleanup, | ||
| 1086 | }, | ||
| 1087 | |||
| 1088 | #ifdef CONFIG_HIGHMEM | 1009 | #ifdef CONFIG_HIGHMEM |
| 1089 | 1010 | ||
| 1090 | { | 1011 | { |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 3ee5b8c3b5c..044d84eeed7 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -121,6 +121,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) | |||
| 121 | { | 121 | { |
| 122 | #ifdef CONFIG_MMC_DEBUG | 122 | #ifdef CONFIG_MMC_DEBUG |
| 123 | unsigned int i, sz; | 123 | unsigned int i, sz; |
| 124 | struct scatterlist *sg; | ||
| 124 | #endif | 125 | #endif |
| 125 | 126 | ||
| 126 | pr_debug("%s: starting CMD%u arg %08x flags %08x\n", | 127 | pr_debug("%s: starting CMD%u arg %08x flags %08x\n", |
| @@ -156,8 +157,8 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) | |||
| 156 | 157 | ||
| 157 | #ifdef CONFIG_MMC_DEBUG | 158 | #ifdef CONFIG_MMC_DEBUG |
| 158 | sz = 0; | 159 | sz = 0; |
| 159 | for (i = 0;i < mrq->data->sg_len;i++) | 160 | for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i) |
| 160 | sz += mrq->data->sg[i].length; | 161 | sz += sg->length; |
| 161 | BUG_ON(sz != mrq->data->blocks * mrq->data->blksz); | 162 | BUG_ON(sz != mrq->data->blocks * mrq->data->blksz); |
| 162 | #endif | 163 | #endif |
| 163 | 164 | ||
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index 99b20917cc0..d3f55615c09 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c | |||
| @@ -61,7 +61,13 @@ | |||
| 61 | 61 | ||
| 62 | /* Hardware definitions */ | 62 | /* Hardware definitions */ |
| 63 | #define AU1XMMC_DESCRIPTOR_COUNT 1 | 63 | #define AU1XMMC_DESCRIPTOR_COUNT 1 |
| 64 | #define AU1XMMC_DESCRIPTOR_SIZE 2048 | 64 | |
| 65 | /* max DMA seg size: 64KB on Au1100, 4MB on Au1200 */ | ||
| 66 | #ifdef CONFIG_SOC_AU1100 | ||
| 67 | #define AU1XMMC_DESCRIPTOR_SIZE 0x0000ffff | ||
| 68 | #else /* Au1200 */ | ||
| 69 | #define AU1XMMC_DESCRIPTOR_SIZE 0x003fffff | ||
| 70 | #endif | ||
| 65 | 71 | ||
| 66 | #define AU1XMMC_OCR (MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \ | 72 | #define AU1XMMC_OCR (MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | \ |
| 67 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \ | 73 | MMC_VDD_30_31 | MMC_VDD_31_32 | MMC_VDD_32_33 | \ |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index deb607c52c0..fcb14c2346c 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
| @@ -143,7 +143,8 @@ static int jmicron_probe(struct sdhci_pci_chip *chip) | |||
| 143 | chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR | | 143 | chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR | |
| 144 | SDHCI_QUIRK_32BIT_DMA_SIZE | | 144 | SDHCI_QUIRK_32BIT_DMA_SIZE | |
| 145 | SDHCI_QUIRK_32BIT_ADMA_SIZE | | 145 | SDHCI_QUIRK_32BIT_ADMA_SIZE | |
| 146 | SDHCI_QUIRK_RESET_AFTER_REQUEST; | 146 | SDHCI_QUIRK_RESET_AFTER_REQUEST | |
| 147 | SDHCI_QUIRK_BROKEN_SMALL_PIO; | ||
| 147 | } | 148 | } |
| 148 | 149 | ||
| 149 | /* | 150 | /* |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 5f95e10229b..e3a8133560a 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -278,6 +278,15 @@ static void sdhci_transfer_pio(struct sdhci_host *host) | |||
| 278 | else | 278 | else |
| 279 | mask = SDHCI_SPACE_AVAILABLE; | 279 | mask = SDHCI_SPACE_AVAILABLE; |
| 280 | 280 | ||
| 281 | /* | ||
| 282 | * Some controllers (JMicron JMB38x) mess up the buffer bits | ||
| 283 | * for transfers < 4 bytes. As long as it is just one block, | ||
| 284 | * we can ignore the bits. | ||
| 285 | */ | ||
| 286 | if ((host->quirks & SDHCI_QUIRK_BROKEN_SMALL_PIO) && | ||
| 287 | (host->data->blocks == 1)) | ||
| 288 | mask = ~0; | ||
| 289 | |||
| 281 | while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) { | 290 | while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) { |
| 282 | if (host->data->flags & MMC_DATA_READ) | 291 | if (host->data->flags & MMC_DATA_READ) |
| 283 | sdhci_read_block_pio(host); | 292 | sdhci_read_block_pio(host); |
| @@ -439,7 +448,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, | |||
| 439 | 448 | ||
| 440 | host->adma_addr = dma_map_single(mmc_dev(host->mmc), | 449 | host->adma_addr = dma_map_single(mmc_dev(host->mmc), |
| 441 | host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); | 450 | host->adma_desc, (128 * 2 + 1) * 4, DMA_TO_DEVICE); |
| 442 | if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr)) | 451 | if (dma_mapping_error(mmc_dev(host->mmc), host->adma_addr)) |
| 443 | goto unmap_entries; | 452 | goto unmap_entries; |
| 444 | BUG_ON(host->adma_addr & 0x3); | 453 | BUG_ON(host->adma_addr & 0x3); |
| 445 | 454 | ||
| @@ -645,7 +654,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
| 645 | * us an invalid request. | 654 | * us an invalid request. |
| 646 | */ | 655 | */ |
| 647 | WARN_ON(1); | 656 | WARN_ON(1); |
| 648 | host->flags &= ~SDHCI_USE_DMA; | 657 | host->flags &= ~SDHCI_REQ_USE_DMA; |
| 649 | } else { | 658 | } else { |
| 650 | writel(host->adma_addr, | 659 | writel(host->adma_addr, |
| 651 | host->ioaddr + SDHCI_ADMA_ADDRESS); | 660 | host->ioaddr + SDHCI_ADMA_ADDRESS); |
| @@ -664,7 +673,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
| 664 | * us an invalid request. | 673 | * us an invalid request. |
| 665 | */ | 674 | */ |
| 666 | WARN_ON(1); | 675 | WARN_ON(1); |
| 667 | host->flags &= ~SDHCI_USE_DMA; | 676 | host->flags &= ~SDHCI_REQ_USE_DMA; |
| 668 | } else { | 677 | } else { |
| 669 | WARN_ON(sg_cnt != 1); | 678 | WARN_ON(sg_cnt != 1); |
| 670 | writel(sg_dma_address(data->sg), | 679 | writel(sg_dma_address(data->sg), |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index e354faee5df..197d4a05f4a 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
| @@ -206,6 +206,8 @@ struct sdhci_host { | |||
| 206 | #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11) | 206 | #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<11) |
| 207 | /* Controller provides an incorrect timeout value for transfers */ | 207 | /* Controller provides an incorrect timeout value for transfers */ |
| 208 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) | 208 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) |
| 209 | /* Controller has an issue with buffer bits for small transfers */ | ||
| 210 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) | ||
| 209 | 211 | ||
| 210 | int irq; /* Device IRQ */ | 212 | int irq; /* Device IRQ */ |
| 211 | void __iomem * ioaddr; /* Mapped address */ | 213 | void __iomem * ioaddr; /* Mapped address */ |
