diff options
author | Christoph Hellwig <hch@lst.de> | 2018-05-18 19:18:46 +0200 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2018-05-21 15:49:21 +0200 |
commit | 9181ece38c93679ec413580f9ddf05b5cdb214db (patch) | |
tree | ce07365d42750d9d096465c00f11c5f1ce538cf8 /drivers/mmc | |
parent | a4034173822e6a9092245f546739946489f8f30d (diff) |
mmc: wbsd: handle highmem pages
Use sg_copy_{from,to}_buffer to bounce buffer and kmap_atomic to map the
scatterlist entry before using it.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/wbsd.c | 68 |
1 files changed, 30 insertions, 38 deletions
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index f4233576153b..1e54bbf13d75 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -268,43 +268,29 @@ static inline int wbsd_next_sg(struct wbsd_host *host) return host->num_sg; } -static inline char *wbsd_sg_to_buffer(struct wbsd_host *host) +static inline char *wbsd_map_sg(struct wbsd_host *host) { - return sg_virt(host->cur_sg); + return kmap_atomic(sg_page(host->cur_sg)) + host->cur_sg->offset; } static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data) { - unsigned int len, i; - struct scatterlist *sg; - char *dmabuf = host->dma_buffer; - char *sgbuf; - - sg = data->sg; - len = data->sg_len; - - for (i = 0; i < len; i++) { - sgbuf = sg_virt(&sg[i]); - memcpy(dmabuf, sgbuf, sg[i].length); - dmabuf += sg[i].length; - } + size_t len = 0; + int i; + + for (i = 0; i < data->sg_len; i++) + len += data->sg[i].length; + sg_copy_to_buffer(data->sg, data->sg_len, host->dma_buffer, len); } static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) { - unsigned int len, i; - struct scatterlist *sg; - char *dmabuf = host->dma_buffer; - char *sgbuf; - - sg = data->sg; - len = data->sg_len; - - for (i = 0; i < len; i++) { - sgbuf = sg_virt(&sg[i]); - memcpy(sgbuf, dmabuf, sg[i].length); - dmabuf += sg[i].length; - } + size_t len = 0; + int i; + + for (i = 0; i < data->sg_len; i++) + len += data->sg[i].length; + sg_copy_from_buffer(data->sg, data->sg_len, host->dma_buffer, len); } /* @@ -418,7 +404,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host) { struct mmc_data *data = host->mrq->cmd->data; char *buffer; - int i, fsr, fifo; + int i, idx, fsr, fifo; /* * Handle excessive data. @@ -426,7 +412,8 @@ static void wbsd_empty_fifo(struct wbsd_host *host) if (host->num_sg == 0) return; - buffer = wbsd_sg_to_buffer(host) + host->offset; + buffer = wbsd_map_sg(host) + host->offset; + idx = 0; /* * Drain the fifo. This has a tendency to loop longer @@ -445,8 +432,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host) fifo = 1; for (i = 0; i < fifo; i++) { - *buffer = inb(host->base + WBSD_DFR); - buffer++; + buffer[idx++] = inb(host->base + WBSD_DFR); host->offset++; host->remain--; @@ -456,16 +442,19 @@ static void wbsd_empty_fifo(struct wbsd_host *host) * End of scatter list entry? */ if (host->remain == 0) { + kunmap_atomic(buffer); /* * Get next entry. Check if last. */ if (!wbsd_next_sg(host)) return; - buffer = wbsd_sg_to_buffer(host); + buffer = wbsd_map_sg(host); + idx = 0; } } } + kunmap_atomic(buffer); /* * This is a very dirty hack to solve a @@ -480,7 +469,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host) { struct mmc_data *data = host->mrq->cmd->data; char *buffer; - int i, fsr, fifo; + int i, idx, fsr, fifo; /* * Check that we aren't being called after the @@ -489,7 +478,8 @@ static void wbsd_fill_fifo(struct wbsd_host *host) if (host->num_sg == 0) return; - buffer = wbsd_sg_to_buffer(host) + host->offset; + buffer = wbsd_map_sg(host) + host->offset; + idx = 0; /* * Fill the fifo. This has a tendency to loop longer @@ -508,8 +498,7 @@ static void wbsd_fill_fifo(struct wbsd_host *host) fifo = 15; for (i = 16; i > fifo; i--) { - outb(*buffer, host->base + WBSD_DFR); - buffer++; + outb(buffer[idx], host->base + WBSD_DFR); host->offset++; host->remain--; @@ -519,16 +508,19 @@ static void wbsd_fill_fifo(struct wbsd_host *host) * End of scatter list entry? */ if (host->remain == 0) { + kunmap_atomic(buffer); /* * Get next entry. Check if last. */ if (!wbsd_next_sg(host)) return; - buffer = wbsd_sg_to_buffer(host); + buffer = wbsd_map_sg(host); + idx = 0; } } } + kunmap_atomic(buffer); /* * The controller stops sending interrupts for |