diff options
Diffstat (limited to 'drivers/mmc/host/tifm_sd.c')
| -rw-r--r-- | drivers/mmc/host/tifm_sd.c | 74 |
1 files changed, 31 insertions, 43 deletions
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index 9fdf7ea06e3f..2cd69c9e9571 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -13,6 +13,7 @@ #include <linux/highmem.h> #include <linux/scatterlist.h> #include <linux/module.h> +#include <linux/workqueue.h> #include <asm/io.h> #define DRIVER_NAME "tifm_sd" @@ -97,7 +98,7 @@ struct tifm_sd { unsigned int clk_div; unsigned long timeout_jiffies; - struct tasklet_struct finish_tasklet; + struct work_struct finish_bh_work; struct timer_list timer; struct mmc_request *req; @@ -116,7 +117,7 @@ static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg, unsigned char *buf; unsigned int pos = 0, val; - buf = kmap_atomic(pg) + off; + buf = kmap_local_page(pg) + off; if (host->cmd_flags & DATA_CARRY) { buf[pos++] = host->bounce_buf_data[0]; host->cmd_flags &= ~DATA_CARRY; @@ -132,7 +133,7 @@ static void tifm_sd_read_fifo(struct tifm_sd *host, struct page *pg, } buf[pos++] = (val >> 8) & 0xff; } - kunmap_atomic(buf - off); + kunmap_local(buf - off); } static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, @@ -142,7 +143,7 @@ static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, unsigned char *buf; unsigned int pos = 0, val; - buf = kmap_atomic(pg) + off; + buf = kmap_local_page(pg) + off; if (host->cmd_flags & DATA_CARRY) { val = host->bounce_buf_data[0] | ((buf[pos++] << 8) & 0xff00); writel(val, sock->addr + SOCK_MMCSD_DATA); @@ -159,7 +160,7 @@ static void tifm_sd_write_fifo(struct tifm_sd *host, struct page *pg, val |= (buf[pos++] << 8) & 0xff00; writel(val, sock->addr + SOCK_MMCSD_DATA); } - kunmap_atomic(buf - off); + kunmap_local(buf - off); } static void tifm_sd_transfer_data(struct tifm_sd *host) @@ -190,7 +191,7 @@ static void tifm_sd_transfer_data(struct tifm_sd *host) } off = sg[host->sg_pos].offset + host->block_pos; - pg = nth_page(sg_page(&sg[host->sg_pos]), off >> PAGE_SHIFT); + pg = sg_page(&sg[host->sg_pos]) + (off >> PAGE_SHIFT); p_off = offset_in_page(off); p_cnt = PAGE_SIZE - p_off; p_cnt = min(p_cnt, cnt); @@ -210,13 +211,13 @@ static void tifm_sd_copy_page(struct page *dst, unsigned int dst_off, struct page *src, unsigned int src_off, unsigned int count) { - unsigned char *src_buf = kmap_atomic(src) + src_off; - unsigned char *dst_buf = kmap_atomic(dst) + dst_off; + unsigned char *src_buf = kmap_local_page(src) + src_off; + unsigned char *dst_buf = kmap_local_page(dst) + dst_off; memcpy(dst_buf, src_buf, count); - kunmap_atomic(dst_buf - dst_off); - kunmap_atomic(src_buf - src_off); + kunmap_local(dst_buf - dst_off); + kunmap_local(src_buf - src_off); } static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data) @@ -239,7 +240,7 @@ static void tifm_sd_bounce_block(struct tifm_sd *host, struct mmc_data *r_data) } off = sg[host->sg_pos].offset + host->block_pos; - pg = nth_page(sg_page(&sg[host->sg_pos]), off >> PAGE_SHIFT); + pg = sg_page(&sg[host->sg_pos]) + (off >> PAGE_SHIFT); p_off = offset_in_page(off); p_cnt = PAGE_SIZE - p_off; p_cnt = min(p_cnt, cnt); @@ -264,16 +265,13 @@ static int tifm_sd_set_dma_data(struct tifm_sd *host, struct mmc_data *r_data) unsigned int t_size = TIFM_DMA_TSIZE * r_data->blksz; unsigned int dma_len, dma_blk_cnt, dma_off; struct scatterlist *sg = NULL; - unsigned long flags; if (host->sg_pos == host->sg_len) return 1; if (host->cmd_flags & DATA_CARRY) { host->cmd_flags &= ~DATA_CARRY; - local_irq_save(flags); tifm_sd_bounce_block(host, r_data); - local_irq_restore(flags); if (host->sg_pos == host->sg_len) return 1; } @@ -300,11 +298,9 @@ static int tifm_sd_set_dma_data(struct tifm_sd *host, struct mmc_data *r_data) if (dma_blk_cnt) sg = &r_data->sg[host->sg_pos]; else if (dma_len) { - if (r_data->flags & MMC_DATA_WRITE) { - local_irq_save(flags); + if (r_data->flags & MMC_DATA_WRITE) tifm_sd_bounce_block(host, r_data); - local_irq_restore(flags); - } else + else host->cmd_flags |= DATA_CARRY; sg = &host->bounce_buf; @@ -468,7 +464,7 @@ static void tifm_sd_check_status(struct tifm_sd *host) } } finish_request: - tasklet_schedule(&host->finish_tasklet); + queue_work(system_bh_wq, &host->finish_bh_work); } /* Called from interrupt handler */ @@ -506,7 +502,6 @@ static void tifm_sd_card_event(struct tifm_dev *sock) unsigned int host_status = 0; int cmd_error = 0; struct mmc_command *cmd = NULL; - unsigned long flags; spin_lock(&sock->lock); host = mmc_priv((struct mmc_host*)tifm_get_drvdata(sock)); @@ -570,9 +565,7 @@ static void tifm_sd_card_event(struct tifm_dev *sock) if (host_status & (TIFM_MMCSD_AE | TIFM_MMCSD_AF | TIFM_MMCSD_BRS)) { - local_irq_save(flags); tifm_sd_transfer_data(host); - local_irq_restore(flags); host_status &= ~TIFM_MMCSD_AE; } } @@ -669,8 +662,8 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) if(1 != tifm_map_sg(sock, &host->bounce_buf, 1, r_data->flags & MMC_DATA_WRITE - ? PCI_DMA_TODEVICE - : PCI_DMA_FROMDEVICE)) { + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE)) { pr_err("%s : scatterlist map failed\n", dev_name(&sock->dev)); mrq->cmd->error = -ENOMEM; @@ -680,15 +673,15 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) r_data->sg_len, r_data->flags & MMC_DATA_WRITE - ? PCI_DMA_TODEVICE - : PCI_DMA_FROMDEVICE); + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE); if (host->sg_len < 1) { pr_err("%s : scatterlist map failed\n", dev_name(&sock->dev)); tifm_unmap_sg(sock, &host->bounce_buf, 1, r_data->flags & MMC_DATA_WRITE - ? PCI_DMA_TODEVICE - : PCI_DMA_FROMDEVICE); + ? DMA_TO_DEVICE + : DMA_FROM_DEVICE); mrq->cmd->error = -ENOMEM; goto err_out; } @@ -731,9 +724,9 @@ err_out: mmc_request_done(mmc, mrq); } -static void tifm_sd_end_cmd(struct tasklet_struct *t) +static void tifm_sd_end_cmd(struct work_struct *t) { - struct tifm_sd *host = from_tasklet(host, t, finish_tasklet); + struct tifm_sd *host = from_work(host, t, finish_bh_work); struct tifm_dev *sock = host->dev; struct mmc_host *mmc = tifm_get_drvdata(sock); struct mmc_request *mrq; @@ -742,7 +735,7 @@ static void tifm_sd_end_cmd(struct tasklet_struct *t) spin_lock_irqsave(&sock->lock, flags); - del_timer(&host->timer); + timer_delete(&host->timer); mrq = host->req; host->req = NULL; @@ -762,10 +755,10 @@ static void tifm_sd_end_cmd(struct tasklet_struct *t) } else { tifm_unmap_sg(sock, &host->bounce_buf, 1, (r_data->flags & MMC_DATA_WRITE) - ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); + ? DMA_TO_DEVICE : DMA_FROM_DEVICE); tifm_unmap_sg(sock, r_data->sg, r_data->sg_len, (r_data->flags & MMC_DATA_WRITE) - ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); + ? DMA_TO_DEVICE : DMA_FROM_DEVICE); } r_data->bytes_xfered = r_data->blocks @@ -784,7 +777,7 @@ static void tifm_sd_end_cmd(struct tasklet_struct *t) static void tifm_sd_abort(struct timer_list *t) { - struct tifm_sd *host = from_timer(host, t, timer); + struct tifm_sd *host = timer_container_of(host, t, timer); pr_err("%s : card failed to respond for a long period of time " "(%x, %x)\n", @@ -954,7 +947,7 @@ static int tifm_sd_probe(struct tifm_dev *sock) return rc; } - mmc = mmc_alloc_host(sizeof(struct tifm_sd), &sock->dev); + mmc = devm_mmc_alloc_host(&sock->dev, sizeof(*host)); if (!mmc) return -ENOMEM; @@ -968,7 +961,7 @@ static int tifm_sd_probe(struct tifm_dev *sock) */ mmc->max_busy_timeout = TIFM_MMCSD_REQ_TIMEOUT_MS; - tasklet_setup(&host->finish_tasklet, tifm_sd_end_cmd); + INIT_WORK(&host->finish_bh_work, tifm_sd_end_cmd); timer_setup(&host->timer, tifm_sd_abort, 0); mmc->ops = &tifm_sd_ops; @@ -989,10 +982,7 @@ static int tifm_sd_probe(struct tifm_dev *sock) if (!rc) rc = mmc_add_host(mmc); - if (!rc) - return 0; - mmc_free_host(mmc); return rc; } @@ -1007,7 +997,7 @@ static void tifm_sd_remove(struct tifm_dev *sock) writel(0, sock->addr + SOCK_MMCSD_INT_ENABLE); spin_unlock_irqrestore(&sock->lock, flags); - tasklet_kill(&host->finish_tasklet); + cancel_work_sync(&host->finish_bh_work); spin_lock_irqsave(&sock->lock, flags); if (host->req) { @@ -1017,13 +1007,11 @@ static void tifm_sd_remove(struct tifm_dev *sock) host->req->cmd->error = -ENOMEDIUM; if (host->req->stop) host->req->stop->error = -ENOMEDIUM; - tasklet_schedule(&host->finish_tasklet); + queue_work(system_bh_wq, &host->finish_bh_work); } spin_unlock_irqrestore(&sock->lock, flags); mmc_remove_host(mmc); dev_dbg(&sock->dev, "after remove\n"); - - mmc_free_host(mmc); } #ifdef CONFIG_PM |
