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:
parent
a403417382
commit
9181ece38c
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user