tifm_sd: use kmap_atomic instead of kmap for PIO data buffer
Data buffer for PIO transfer used to be mapped in advance with kmap. Abolish it in favor of on-demand kmap_atomic. Signed-off-by: Alex Dubov <oakad@yahoo.com> Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
This commit is contained in:
parent
1289335a2a
commit
255ef22e89
|
@ -103,38 +103,51 @@ struct tifm_sd {
|
||||||
wait_queue_head_t can_eject;
|
wait_queue_head_t can_eject;
|
||||||
|
|
||||||
size_t written_blocks;
|
size_t written_blocks;
|
||||||
char *buffer;
|
|
||||||
size_t buffer_size;
|
size_t buffer_size;
|
||||||
size_t buffer_pos;
|
size_t buffer_pos;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static char* tifm_sd_kmap_atomic(struct mmc_data *data)
|
||||||
|
{
|
||||||
|
return kmap_atomic(data->sg->page, KM_BIO_SRC_IRQ) + data->sg->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tifm_sd_kunmap_atomic(char *buffer, struct mmc_data *data)
|
||||||
|
{
|
||||||
|
kunmap_atomic(buffer - data->sg->offset, KM_BIO_SRC_IRQ);
|
||||||
|
}
|
||||||
|
|
||||||
static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host,
|
static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host,
|
||||||
unsigned int host_status)
|
unsigned int host_status)
|
||||||
{
|
{
|
||||||
struct mmc_command *cmd = host->req->cmd;
|
struct mmc_command *cmd = host->req->cmd;
|
||||||
unsigned int t_val = 0, cnt = 0;
|
unsigned int t_val = 0, cnt = 0;
|
||||||
|
char *buffer;
|
||||||
|
|
||||||
if (host_status & TIFM_MMCSD_BRS) {
|
if (host_status & TIFM_MMCSD_BRS) {
|
||||||
/* in non-dma rx mode BRS fires when fifo is still not empty */
|
/* in non-dma rx mode BRS fires when fifo is still not empty */
|
||||||
if (host->buffer && (cmd->data->flags & MMC_DATA_READ)) {
|
if (no_dma && (cmd->data->flags & MMC_DATA_READ)) {
|
||||||
|
buffer = tifm_sd_kmap_atomic(host->req->data);
|
||||||
while (host->buffer_size > host->buffer_pos) {
|
while (host->buffer_size > host->buffer_pos) {
|
||||||
t_val = readl(sock->addr + SOCK_MMCSD_DATA);
|
t_val = readl(sock->addr + SOCK_MMCSD_DATA);
|
||||||
host->buffer[host->buffer_pos++] = t_val & 0xff;
|
buffer[host->buffer_pos++] = t_val & 0xff;
|
||||||
host->buffer[host->buffer_pos++] =
|
buffer[host->buffer_pos++] =
|
||||||
(t_val >> 8) & 0xff;
|
(t_val >> 8) & 0xff;
|
||||||
}
|
}
|
||||||
|
tifm_sd_kunmap_atomic(buffer, host->req->data);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
} else if (host->buffer) {
|
} else if (no_dma) {
|
||||||
|
buffer = tifm_sd_kmap_atomic(host->req->data);
|
||||||
if ((cmd->data->flags & MMC_DATA_READ) &&
|
if ((cmd->data->flags & MMC_DATA_READ) &&
|
||||||
(host_status & TIFM_MMCSD_AF)) {
|
(host_status & TIFM_MMCSD_AF)) {
|
||||||
for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
|
for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
|
||||||
t_val = readl(sock->addr + SOCK_MMCSD_DATA);
|
t_val = readl(sock->addr + SOCK_MMCSD_DATA);
|
||||||
if (host->buffer_size > host->buffer_pos) {
|
if (host->buffer_size > host->buffer_pos) {
|
||||||
host->buffer[host->buffer_pos++] =
|
buffer[host->buffer_pos++] =
|
||||||
t_val & 0xff;
|
t_val & 0xff;
|
||||||
host->buffer[host->buffer_pos++] =
|
buffer[host->buffer_pos++] =
|
||||||
(t_val >> 8) & 0xff;
|
(t_val >> 8) & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,14 +155,16 @@ static int tifm_sd_transfer_data(struct tifm_dev *sock, struct tifm_sd *host,
|
||||||
&& (host_status & TIFM_MMCSD_AE)) {
|
&& (host_status & TIFM_MMCSD_AE)) {
|
||||||
for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
|
for (cnt = 0; cnt < TIFM_MMCSD_FIFO_SIZE; cnt++) {
|
||||||
if (host->buffer_size > host->buffer_pos) {
|
if (host->buffer_size > host->buffer_pos) {
|
||||||
t_val = host->buffer[host->buffer_pos++] & 0x00ff;
|
t_val = buffer[host->buffer_pos++]
|
||||||
t_val |= ((host->buffer[host->buffer_pos++]) << 8)
|
& 0x00ff;
|
||||||
& 0xff00;
|
t_val |= ((buffer[host->buffer_pos++])
|
||||||
|
<< 8) & 0xff00;
|
||||||
writel(t_val,
|
writel(t_val,
|
||||||
sock->addr + SOCK_MMCSD_DATA);
|
sock->addr + SOCK_MMCSD_DATA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tifm_sd_kunmap_atomic(buffer, host->req->data);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -561,15 +576,6 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||||
struct tifm_dev *sock = host->dev;
|
struct tifm_dev *sock = host->dev;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct mmc_data *r_data = mrq->cmd->data;
|
struct mmc_data *r_data = mrq->cmd->data;
|
||||||
char *t_buffer = NULL;
|
|
||||||
|
|
||||||
if (r_data) {
|
|
||||||
t_buffer = kmap(r_data->sg->page);
|
|
||||||
if (!t_buffer) {
|
|
||||||
printk(KERN_ERR DRIVER_NAME ": kmap failed\n");
|
|
||||||
goto err_out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sock->lock, flags);
|
spin_lock_irqsave(&sock->lock, flags);
|
||||||
if (host->flags & EJECT) {
|
if (host->flags & EJECT) {
|
||||||
|
@ -586,7 +592,6 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||||
if (r_data) {
|
if (r_data) {
|
||||||
tifm_sd_set_data_timeout(host, r_data);
|
tifm_sd_set_data_timeout(host, r_data);
|
||||||
|
|
||||||
host->buffer = t_buffer + r_data->sg->offset;
|
|
||||||
host->buffer_size = mrq->cmd->data->blocks *
|
host->buffer_size = mrq->cmd->data->blocks *
|
||||||
mrq->cmd->data->blksz;
|
mrq->cmd->data->blksz;
|
||||||
|
|
||||||
|
@ -615,9 +620,6 @@ static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
if (t_buffer)
|
|
||||||
kunmap(r_data->sg->page);
|
|
||||||
|
|
||||||
mrq->cmd->error = MMC_ERR_TIMEOUT;
|
mrq->cmd->error = MMC_ERR_TIMEOUT;
|
||||||
mmc_request_done(mmc, mrq);
|
mmc_request_done(mmc, mrq);
|
||||||
}
|
}
|
||||||
|
@ -659,7 +661,6 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work)
|
||||||
r_data->bytes_xfered += r_data->blksz -
|
r_data->bytes_xfered += r_data->blksz -
|
||||||
readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
|
readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1;
|
||||||
}
|
}
|
||||||
host->buffer = NULL;
|
|
||||||
host->buffer_pos = 0;
|
host->buffer_pos = 0;
|
||||||
host->buffer_size = 0;
|
host->buffer_size = 0;
|
||||||
}
|
}
|
||||||
|
@ -669,9 +670,6 @@ static void tifm_sd_end_cmd_nodma(struct work_struct *work)
|
||||||
|
|
||||||
spin_unlock_irqrestore(&sock->lock, flags);
|
spin_unlock_irqrestore(&sock->lock, flags);
|
||||||
|
|
||||||
if (r_data)
|
|
||||||
kunmap(r_data->sg->page);
|
|
||||||
|
|
||||||
mmc_request_done(mmc, mrq);
|
mmc_request_done(mmc, mrq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue