X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fmemstick%2Fhost%2Ftifm_ms.c;h=d32d6ad8f3fc5ab51017a6350c7d68aa4c42736b;hb=4b1fefaca9f5fdd43b24aa248777a75a81dfa8d6;hp=2b5bf52a8302b81be8ac1464548d5490eb085a1f;hpb=c523aef0f7284970463ebd77a54bca9069711d4a;p=linux-2.6-omap-h63xx.git diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index 2b5bf52a830..d32d6ad8f3f 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -71,6 +71,7 @@ struct tifm_ms { struct tifm_dev *dev; struct timer_list timer; struct memstick_request *req; + struct tasklet_struct notify; unsigned int mode_mask; unsigned int block_pos; unsigned long timeout_jiffies; @@ -182,7 +183,7 @@ static unsigned int tifm_ms_transfer_data(struct tifm_ms *host) struct tifm_dev *sock = host->dev; unsigned int length; unsigned int off; - unsigned int t_size, p_off, p_cnt; + unsigned int t_size, p_cnt; unsigned char *buf; struct page *pg; unsigned long flags = 0; @@ -198,6 +199,8 @@ static unsigned int tifm_ms_transfer_data(struct tifm_ms *host) host->block_pos); while (length) { + unsigned int uninitialized_var(p_off); + if (host->req->long_data) { pg = nth_page(sg_page(&host->req->sg), off >> PAGE_SHIFT); @@ -340,11 +343,20 @@ static void tifm_ms_complete_cmd(struct tifm_ms *host) del_timer(&host->timer); - if (host->use_dma) + host->req->int_reg = readl(sock->addr + SOCK_MS_STATUS) & 0xff; + host->req->int_reg = (host->req->int_reg & 1) + | ((host->req->int_reg << 4) & 0xe0); + + writel(TIFM_FIFO_INT_SETALL, + sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); + writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); + + if (host->use_dma) { tifm_unmap_sg(sock, &host->req->sg, 1, host->req->data_dir == READ ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); + } writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); @@ -424,12 +436,6 @@ static void tifm_ms_card_event(struct tifm_dev *sock) else if (host_status & TIFM_MS_STAT_CRC) host->req->error = -EILSEQ; - if (host->req->error) { - writel(TIFM_FIFO_INT_SETALL, - sock->addr + SOCK_DMA_FIFO_INT_ENABLE_CLEAR); - writel(TIFM_DMA_RESET, sock->addr + SOCK_DMA_CONTROL); - } - if (host_status & TIFM_MS_STAT_RDY) host->cmd_flags |= CMD_READY; @@ -450,49 +456,51 @@ static void tifm_ms_card_event(struct tifm_dev *sock) return; } -static void tifm_ms_request(struct memstick_host *msh) +static void tifm_ms_req_tasklet(unsigned long data) { + struct memstick_host *msh = (struct memstick_host *)data; struct tifm_ms *host = memstick_priv(msh); struct tifm_dev *sock = host->dev; unsigned long flags; int rc; spin_lock_irqsave(&sock->lock, flags); - if (host->req) { - printk(KERN_ERR "%s : unfinished request detected\n", - sock->dev.bus_id); - spin_unlock_irqrestore(&sock->lock, flags); - tifm_eject(host->dev); - return; - } + if (!host->req) { + if (host->eject) { + do { + rc = memstick_next_req(msh, &host->req); + if (!rc) + host->req->error = -ETIME; + } while (!rc); + spin_unlock_irqrestore(&sock->lock, flags); + return; + } - if (host->eject) { do { rc = memstick_next_req(msh, &host->req); - if (!rc) - host->req->error = -ETIME; - } while (!rc); - spin_unlock_irqrestore(&sock->lock, flags); - return; + } while (!rc && tifm_ms_issue_cmd(host)); } - - do { - rc = memstick_next_req(msh, &host->req); - } while (!rc && tifm_ms_issue_cmd(host)); - spin_unlock_irqrestore(&sock->lock, flags); +} + +static void tifm_ms_dummy_submit(struct memstick_host *msh) +{ return; } -static void tifm_ms_set_param(struct memstick_host *msh, - enum memstick_param param, - int value) +static void tifm_ms_submit_req(struct memstick_host *msh) { struct tifm_ms *host = memstick_priv(msh); - struct tifm_dev *sock = host->dev; - unsigned long flags; - spin_lock_irqsave(&sock->lock, flags); + tasklet_schedule(&host->notify); +} + +static int tifm_ms_set_param(struct memstick_host *msh, + enum memstick_param param, + int value) +{ + struct tifm_ms *host = memstick_priv(msh); + struct tifm_dev *sock = host->dev; switch (param) { case MEMSTICK_POWER: @@ -507,7 +515,8 @@ static void tifm_ms_set_param(struct memstick_host *msh, writel(TIFM_MS_SYS_FCLR | TIFM_MS_SYS_INTCLR, sock->addr + SOCK_MS_SYSTEM); writel(0xffffffff, sock->addr + SOCK_MS_STATUS); - } + } else + return -EINVAL; break; case MEMSTICK_INTERFACE: if (value == MEMSTICK_SERIAL) { @@ -520,11 +529,12 @@ static void tifm_ms_set_param(struct memstick_host *msh, writel(TIFM_CTRL_FAST_CLK | readl(sock->addr + SOCK_CONTROL), sock->addr + SOCK_CONTROL); - } + } else + return -EINVAL; break; }; - spin_unlock_irqrestore(&sock->lock, flags); + return 0; } static void tifm_ms_abort(unsigned long data) @@ -565,8 +575,9 @@ static int tifm_ms_probe(struct tifm_dev *sock) host->timeout_jiffies = msecs_to_jiffies(1000); setup_timer(&host->timer, tifm_ms_abort, (unsigned long)host); + tasklet_init(&host->notify, tifm_ms_req_tasklet, (unsigned long)msh); - msh->request = tifm_ms_request; + msh->request = tifm_ms_submit_req; msh->set_param = tifm_ms_set_param; sock->card_event = tifm_ms_card_event; sock->data_event = tifm_ms_data_event; @@ -588,6 +599,8 @@ static void tifm_ms_remove(struct tifm_dev *sock) int rc = 0; unsigned long flags; + msh->request = tifm_ms_dummy_submit; + tasklet_kill(&host->notify); spin_lock_irqsave(&sock->lock, flags); host->eject = 1; if (host->req) {