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;
}
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;
size_t len = 0;
int i;
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;
}
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;
size_t len = 0;
int i;
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;
}
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