Commit 12658af5 authored by Linus Walleij's avatar Linus Walleij Committed by Ulf Hansson

mmc: mxcmmc: Use sg_miter for PIO

Use the scatterlist memory iterator instead of just
dereferencing virtual memory using sg_virt().
This make highmem references work properly.

Since this driver is using a worker, no atomic trickery
is needed.
Suggested-by: default avatarChristoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/linux-mmc/20240122073423.GA25859@lst.de/Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20240127-mmc-proper-kmap-v2-6-d8e732aa97d1@linaro.orgSigned-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 2761822c
...@@ -266,11 +266,18 @@ static inline void buffer_swap32(u32 *buf, int len) ...@@ -266,11 +266,18 @@ static inline void buffer_swap32(u32 *buf, int len)
static void mxcmci_swap_buffers(struct mmc_data *data) static void mxcmci_swap_buffers(struct mmc_data *data)
{ {
struct scatterlist *sg; struct sg_mapping_iter sgm;
int i; u32 *buf;
sg_miter_start(&sgm, data->sg, data->sg_len,
SG_MITER_TO_SG | SG_MITER_FROM_SG);
while (sg_miter_next(&sgm)) {
buf = sgm.addr;
buffer_swap32(buf, sgm.length);
}
for_each_sg(data->sg, sg, data->sg_len, i) sg_miter_stop(&sgm);
buffer_swap32(sg_virt(sg), sg->length);
} }
#else #else
static inline void mxcmci_swap_buffers(struct mmc_data *data) {} static inline void mxcmci_swap_buffers(struct mmc_data *data) {}
...@@ -526,10 +533,9 @@ static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask) ...@@ -526,10 +533,9 @@ static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask)
} while (1); } while (1);
} }
static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes) static int mxcmci_pull(struct mxcmci_host *host, u32 *buf, int bytes)
{ {
unsigned int stat; unsigned int stat;
u32 *buf = _buf;
while (bytes > 3) { while (bytes > 3) {
stat = mxcmci_poll_status(host, stat = mxcmci_poll_status(host,
...@@ -555,10 +561,9 @@ static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes) ...@@ -555,10 +561,9 @@ static int mxcmci_pull(struct mxcmci_host *host, void *_buf, int bytes)
return 0; return 0;
} }
static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes) static int mxcmci_push(struct mxcmci_host *host, u32 *buf, int bytes)
{ {
unsigned int stat; unsigned int stat;
u32 *buf = _buf;
while (bytes > 3) { while (bytes > 3) {
stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY); stat = mxcmci_poll_status(host, STATUS_BUF_WRITE_RDY);
...@@ -586,31 +591,39 @@ static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes) ...@@ -586,31 +591,39 @@ static int mxcmci_push(struct mxcmci_host *host, void *_buf, int bytes)
static int mxcmci_transfer_data(struct mxcmci_host *host) static int mxcmci_transfer_data(struct mxcmci_host *host)
{ {
struct mmc_data *data = host->req->data; struct mmc_data *data = host->req->data;
struct scatterlist *sg; struct sg_mapping_iter sgm;
int stat, i; int stat;
u32 *buf;
host->data = data; host->data = data;
host->datasize = 0; host->datasize = 0;
sg_miter_start(&sgm, data->sg, data->sg_len,
(data->flags & MMC_DATA_READ) ? SG_MITER_TO_SG : SG_MITER_FROM_SG);
if (data->flags & MMC_DATA_READ) { if (data->flags & MMC_DATA_READ) {
for_each_sg(data->sg, sg, data->sg_len, i) { while (sg_miter_next(&sgm)) {
stat = mxcmci_pull(host, sg_virt(sg), sg->length); buf = sgm.addr;
stat = mxcmci_pull(host, buf, sgm.length);
if (stat) if (stat)
return stat; goto transfer_error;
host->datasize += sg->length; host->datasize += sgm.length;
} }
} else { } else {
for_each_sg(data->sg, sg, data->sg_len, i) { while (sg_miter_next(&sgm)) {
stat = mxcmci_push(host, sg_virt(sg), sg->length); buf = sgm.addr;
stat = mxcmci_push(host, buf, sgm.length);
if (stat) if (stat)
return stat; goto transfer_error;
host->datasize += sg->length; host->datasize += sgm.length;
} }
stat = mxcmci_poll_status(host, STATUS_WRITE_OP_DONE); stat = mxcmci_poll_status(host, STATUS_WRITE_OP_DONE);
if (stat) if (stat)
return stat; goto transfer_error;
} }
return 0;
transfer_error:
sg_miter_stop(&sgm);
return stat;
} }
static void mxcmci_datawork(struct work_struct *work) static void mxcmci_datawork(struct work_struct *work)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment