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>
This commit is contained in:
Christoph Hellwig 2018-05-18 19:18:46 +02:00 committed by Ulf Hansson
parent a403417382
commit 9181ece38c

View File

@ -268,43 +268,29 @@ static inline int wbsd_next_sg(struct wbsd_host *host)
return host->num_sg; 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) static inline void wbsd_sg_to_dma(struct wbsd_host *host, struct mmc_data *data)
{ {
unsigned int len, i; size_t len = 0;
struct scatterlist *sg; int i;
char *dmabuf = host->dma_buffer;
char *sgbuf;
sg = data->sg; for (i = 0; i < data->sg_len; i++)
len = data->sg_len; len += data->sg[i].length;
sg_copy_to_buffer(data->sg, data->sg_len, host->dma_buffer, len);
for (i = 0; i < len; i++) {
sgbuf = sg_virt(&sg[i]);
memcpy(dmabuf, sgbuf, sg[i].length);
dmabuf += sg[i].length;
}
} }
static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data) static inline void wbsd_dma_to_sg(struct wbsd_host *host, struct mmc_data *data)
{ {
unsigned int len, i; size_t len = 0;
struct scatterlist *sg; int i;
char *dmabuf = host->dma_buffer;
char *sgbuf;
sg = data->sg; for (i = 0; i < data->sg_len; i++)
len = data->sg_len; len += data->sg[i].length;
sg_copy_from_buffer(data->sg, data->sg_len, host->dma_buffer, len);
for (i = 0; i < len; i++) {
sgbuf = sg_virt(&sg[i]);
memcpy(sgbuf, dmabuf, sg[i].length);
dmabuf += sg[i].length;
}
} }
/* /*
@ -418,7 +404,7 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
{ {
struct mmc_data *data = host->mrq->cmd->data; struct mmc_data *data = host->mrq->cmd->data;
char *buffer; char *buffer;
int i, fsr, fifo; int i, idx, fsr, fifo;
/* /*
* Handle excessive data. * Handle excessive data.
@ -426,7 +412,8 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
if (host->num_sg == 0) if (host->num_sg == 0)
return; 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 * 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; fifo = 1;
for (i = 0; i < fifo; i++) { for (i = 0; i < fifo; i++) {
*buffer = inb(host->base + WBSD_DFR); buffer[idx++] = inb(host->base + WBSD_DFR);
buffer++;
host->offset++; host->offset++;
host->remain--; host->remain--;
@ -456,16 +442,19 @@ static void wbsd_empty_fifo(struct wbsd_host *host)
* End of scatter list entry? * End of scatter list entry?
*/ */
if (host->remain == 0) { if (host->remain == 0) {
kunmap_atomic(buffer);
/* /*
* Get next entry. Check if last. * Get next entry. Check if last.
*/ */
if (!wbsd_next_sg(host)) if (!wbsd_next_sg(host))
return; 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 * 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; struct mmc_data *data = host->mrq->cmd->data;
char *buffer; char *buffer;
int i, fsr, fifo; int i, idx, fsr, fifo;
/* /*
* Check that we aren't being called after the * 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) if (host->num_sg == 0)
return; 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 * 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; fifo = 15;
for (i = 16; i > fifo; i--) { for (i = 16; i > fifo; i--) {
outb(*buffer, host->base + WBSD_DFR); outb(buffer[idx], host->base + WBSD_DFR);
buffer++;
host->offset++; host->offset++;
host->remain--; host->remain--;
@ -519,16 +508,19 @@ static void wbsd_fill_fifo(struct wbsd_host *host)
* End of scatter list entry? * End of scatter list entry?
*/ */
if (host->remain == 0) { if (host->remain == 0) {
kunmap_atomic(buffer);
/* /*
* Get next entry. Check if last. * Get next entry. Check if last.
*/ */
if (!wbsd_next_sg(host)) if (!wbsd_next_sg(host))
return; return;
buffer = wbsd_sg_to_buffer(host); buffer = wbsd_map_sg(host);
idx = 0;
} }
} }
} }
kunmap_atomic(buffer);
/* /*
* The controller stops sending interrupts for * The controller stops sending interrupts for