Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9181ece3 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Ulf Hansson
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent a4034173
Loading
Loading
Loading
Loading
+30 −38
Original line number Diff line number Diff line
@@ -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;
	size_t len = 0;
	int i;

	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;

	sg = data->sg;
	len = data->sg_len;
	size_t len = 0;
	int i;

	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