diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/tifm_sd.c | 52 |
1 files changed, 25 insertions, 27 deletions
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c index f22c3968f2d4..3e762770afcb 100644 --- a/drivers/mmc/tifm_sd.c +++ b/drivers/mmc/tifm_sd.c | |||
@@ -103,38 +103,51 @@ struct tifm_sd { | |||
103 | wait_queue_head_t can_eject; | 103 | wait_queue_head_t can_eject; |
104 | 104 | ||
105 | size_t written_blocks; | 105 | size_t written_blocks; |
106 | char *buffer; | ||
107 | size_t buffer_size; | 106 | size_t buffer_size; |
108 | size_t buffer_pos; | 107 | size_t buffer_pos; |
109 | 108 | ||
110 | }; | 109 | }; |
111 | 110 | ||
111 | static char* tifm_sd_kmap_atomic(struct mmc_data *data) | ||
112 | { | ||
113 | return kmap_atomic(data->sg->page, KM_BIO_SRC_IRQ) + data->sg->offset; | ||
114 | } | ||
115 | |||
116 | static void tifm_sd_kunmap_atomic(char *buffer, struct mmc_data *data) | ||
117 | { | ||
118 | kunmap_atomic(buffer - data->sg->offset, KM_BIO_SRC_IRQ); | ||
119 | } | ||
120 | |||
112 | static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, | 121 | static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, |
113 | unsigned int host_status) | 122 | unsigned int host_status) |
114 | { | 123 | { |
115 | struct mmc_command *cmd = host->req->cmd; | 124 | struct mmc_command *cmd = host->req->cmd; |
116 | unsigned int t_val = 0, cnt = 0; | 125 | unsigned int t_val = 0, cnt = 0; |
126 | char *buffer; | ||
117 | 127 | ||
118 | if (host_status & TIFM_MMCSD_BRS) { | 128 | if (host_status & TIFM_MMCSD_BRS) { |
119 | /* in non-dma rx mode BRS fires when fifo is still not empty */ | 129 | /* in non-dma rx mode BRS fires when fifo is still not empty */ |
120 | if (host->buffer && (cmd->data->flags & MMC_DATA_READ)) { | 130 | if (no_dma && (cmd->data->flags & MMC_DATA_READ)) { |
131 | buffer = tifm_sd_kmap_atomic(host->req->data); | ||
121 | while (host->buffer_size > host->buffer_pos) { | 132 | while (host->buffer_size > host->buffer_pos) { |
122 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); | 133 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); |
123 | host->buffer[host->buffer_pos++] = t_val & 0xff; | 134 | buffer[host->buffer_pos++] = t_val & 0xff; |
124 | host->buffer[host->buffer_pos++] = | 135 | buffer[host->buffer_pos++] = |
125 | (t_val >> 8) & 0xff; | 136 | (t_val >> 8) & 0xff; |
126 | } | 137 | } |
138 | tifm_sd_kunmap_atomic(buffer, host->req->data); | ||
127 | } | 139 | } |
128 | return 1; | 140 | return 1; |
129 | } else if (host->buffer) { | 141 | } else if (no_dma) { |
142 | buffer = tifm_sd_kmap_atomic(host->req->data); | ||
130 | if ((cmd->data->flags & MMC_DATA_READ) && | 143 | if ((cmd->data->flags & MMC_DATA_READ) && |
131 | (host_status & TIFM_MMCSD_AF)) { | 144 | (host_status & TIFM_MMCSD_AF)) { |
132 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { | 145 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { |
133 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); | 146 | t_val = readl(sock->addr + SOCK_MMCSD_DATA); |
134 | if (host->buffer_size > host->buffer_pos) { | 147 | if (host->buffer_size > host->buffer_pos) { |
135 | host->buffer[host->buffer_pos++] = | 148 | buffer[host->buffer_pos++] = |
136 | t_val & 0xff; | 149 | t_val & 0xff; |
137 | host->buffer[host->buffer_pos++] = | 150 | buffer[host->buffer_pos++] = |
138 | (t_val >> 8) & 0xff; | 151 | (t_val >> 8) & 0xff; |
139 | } | 152 | } |
140 | } | 153 | } |
@@ -142,14 +155,16 @@ static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host, | |||
142 | && (host_status & TIFM_MMCSD_AE)) { | 155 | && (host_status & TIFM_MMCSD_AE)) { |
143 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { | 156 | for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) { |
144 | if (host->buffer_size > host->buffer_pos) { | 157 | if (host->buffer_size > host->buffer_pos) { |
145 | t_val = host->buffer[host->buffer_pos++] & 0x00ff; | 158 | t_val = buffer[host->buffer_pos++] |
146 | t_val |= ((host->buffer[host->buffer_pos++]) << 8) | 159 | & 0x00ff; |
147 | & 0xff00; | 160 | t_val |= ((buffer[host->buffer_pos++]) |
161 | << 8) & 0xff00; | ||
148 | writel(t_val, | 162 | writel(t_val, |
149 | sock->addr + SOCK_MMCSD_DATA); | 163 | sock->addr + SOCK_MMCSD_DATA); |
150 | } | 164 | } |
151 | } | 165 | } |
152 | } | 166 | } |
167 | tifm_sd_kunmap_atomic(buffer, host->req->data); | ||
153 | } | 168 | } |
154 | return 0; | 169 | return 0; |
155 | } | 170 | } |
@@ -561,15 +576,6 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | |||
561 | struct tifm_dev *sock = host->dev; | 576 | struct tifm_dev *sock = host->dev; |
562 | unsigned long flags; | 577 | unsigned long flags; |
563 | struct mmc_data *r_data = mrq->cmd->data; | 578 | struct mmc_data *r_data = mrq->cmd->data; |
564 | char *t_buffer = NULL; | ||
565 | |||
566 | if (r_data) { | ||
567 | t_buffer = kmap(r_data->sg->page); | ||
568 | if (!t_buffer) { | ||
569 | printk(KERN_ERR DRIVER_NAME ": kmap failed\n"); | ||
570 | goto err_out; | ||
571 | } | ||
572 | } | ||
573 | 579 | ||
574 | spin_lock_irqsave(&sock->lock, flags); | 580 | spin_lock_irqsave(&sock->lock, flags); |
575 | if (host->flags & EJECT) { | 581 | if (host->flags & EJECT) { |
@@ -586,7 +592,6 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | |||
586 | if (r_data) { | 592 | if (r_data) { |
587 | tifm_sd_set_data_timeout(host, r_data); | 593 | tifm_sd_set_data_timeout(host, r_data); |
588 | 594 | ||
589 | host->buffer = t_buffer + r_data->sg->offset; | ||
590 | host->buffer_size = mrq->cmd->data->blocks * | 595 | host->buffer_size = mrq->cmd->data->blocks * |
591 | mrq->cmd->data->blksz; | 596 | mrq->cmd->data->blksz; |
592 | 597 | ||
@@ -615,9 +620,6 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | |||
615 | return; | 620 | return; |
616 | 621 | ||
617 | err_out: | 622 | err_out: |
618 | if (t_buffer) | ||
619 | kunmap(r_data->sg->page); | ||
620 | |||
621 | mrq->cmd->error = MMC_ERR_TIMEOUT; | 623 | mrq->cmd->error = MMC_ERR_TIMEOUT; |
622 | mmc_request_done(mmc, mrq); | 624 | mmc_request_done(mmc, mrq); |
623 | } | 625 | } |
@@ -659,7 +661,6 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work) | |||
659 | r_data->bytes_xfered += r_data->blksz - | 661 | r_data->bytes_xfered += r_data->blksz - |
660 | readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; | 662 | readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; |
661 | } | 663 | } |
662 | host->buffer = NULL; | ||
663 | host->buffer_pos = 0; | 664 | host->buffer_pos = 0; |
664 | host->buffer_size = 0; | 665 | host->buffer_size = 0; |
665 | } | 666 | } |
@@ -669,9 +670,6 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work) | |||
669 | 670 | ||
670 | spin_unlock_irqrestore(&sock->lock, flags); | 671 | spin_unlock_irqrestore(&sock->lock, flags); |
671 | 672 | ||
672 | if (r_data) | ||
673 | kunmap(r_data->sg->page); | ||
674 | |||
675 | mmc_request_done(mmc, mrq); | 673 | mmc_request_done(mmc, mrq); |
676 | } | 674 | } |
677 | 675 | ||