Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 201492
b: refs/heads/master
c: 4ce1d6c
h: refs/heads/master
v: v3
  • Loading branch information
Rabin Vincent authored and Russell King committed Jul 27, 2010
1 parent 9c64dab commit 51e653f
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 57 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2c39c9e149f45ec15a6985cb06ec8f6d904bb35e
refs/heads/master: 4ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7
60 changes: 38 additions & 22 deletions trunk/drivers/mmc/host/mmci.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include <linux/amba/mmci.h>
#include <linux/regulator/consumer.h>

#include <asm/cacheflush.h>
#include <asm/div64.h>
#include <asm/io.h>
#include <asm/sizes.h>
Expand Down Expand Up @@ -98,6 +97,18 @@ static void mmci_stop_data(struct mmci_host *host)
host->data = NULL;
}

static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
{
unsigned int flags = SG_MITER_ATOMIC;

if (data->flags & MMC_DATA_READ)
flags |= SG_MITER_TO_SG;
else
flags |= SG_MITER_FROM_SG;

sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
}

static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
{
unsigned int datactrl, timeout, irqmask;
Expand Down Expand Up @@ -210,8 +221,17 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
* We hit an error condition. Ensure that any data
* partially written to a page is properly coherent.
*/
if (host->sg_len && data->flags & MMC_DATA_READ)
flush_dcache_page(sg_page(host->sg_ptr));
if (data->flags & MMC_DATA_READ) {
struct sg_mapping_iter *sg_miter = &host->sg_miter;
unsigned long flags;

local_irq_save(flags);
if (sg_miter_next(sg_miter)) {
flush_dcache_page(sg_miter->page);
sg_miter_stop(sg_miter);
}
local_irq_restore(flags);
}
}
if (status & MCI_DATAEND) {
mmci_stop_data(host);
Expand Down Expand Up @@ -314,15 +334,18 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem
static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
{
struct mmci_host *host = dev_id;
struct sg_mapping_iter *sg_miter = &host->sg_miter;
void __iomem *base = host->base;
unsigned long flags;
u32 status;

status = readl(base + MMCISTATUS);

dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status);

local_irq_save(flags);

do {
unsigned long flags;
unsigned int remain, len;
char *buffer;

Expand All @@ -336,43 +359,36 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL)))
break;

/*
* Map the current scatter buffer.
*/
buffer = mmci_kmap_atomic(host, &flags) + host->sg_off;
remain = host->sg_ptr->length - host->sg_off;
if (!sg_miter_next(sg_miter))
break;

buffer = sg_miter->addr;
remain = sg_miter->length;

len = 0;
if (status & MCI_RXACTIVE)
len = mmci_pio_read(host, buffer, remain);
if (status & MCI_TXACTIVE)
len = mmci_pio_write(host, buffer, remain, status);

/*
* Unmap the buffer.
*/
mmci_kunmap_atomic(host, buffer, &flags);
sg_miter->consumed = len;

host->sg_off += len;
host->size -= len;
remain -= len;

if (remain)
break;

/*
* If we were reading, and we have completed this
* page, ensure that the data cache is coherent.
*/
if (status & MCI_RXACTIVE)
flush_dcache_page(sg_page(host->sg_ptr));

if (!mmci_next_sg(host))
break;
flush_dcache_page(sg_miter->page);

status = readl(base + MMCISTATUS);
} while (1);

sg_miter_stop(sg_miter);

local_irq_restore(flags);

/*
* If we're nearing the end of the read, switch to
* "any data available" mode.
Expand Down
35 changes: 1 addition & 34 deletions trunk/drivers/mmc/host/mmci.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,42 +171,9 @@ struct mmci_host {
struct timer_list timer;
unsigned int oldstat;

unsigned int sg_len;

/* pio stuff */
struct scatterlist *sg_ptr;
unsigned int sg_off;
struct sg_mapping_iter sg_miter;
unsigned int size;
struct regulator *vcc;
};

static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
{
/*
* Ideally, we want the higher levels to pass us a scatter list.
*/
host->sg_len = data->sg_len;
host->sg_ptr = data->sg;
host->sg_off = 0;
}

static inline int mmci_next_sg(struct mmci_host *host)
{
host->sg_ptr++;
host->sg_off = 0;
return --host->sg_len;
}

static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flags)
{
struct scatterlist *sg = host->sg_ptr;

local_irq_save(*flags);
return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
}

static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags)
{
kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
local_irq_restore(*flags);
}

0 comments on commit 51e653f

Please sign in to comment.