/** * mmc_queue_suspend - suspend a MMC request queue * @mq: MMC queue to suspend * * Stop the block request queue, and wait for our thread to * complete any outstanding requests. This ensures that we * won't suspend while a request is being processed. */ void mmc_queue_suspend(struct mmc_queue *mq) { request_queue_t *q = mq->queue; unsigned long flags; if (!(mq->flags & MMC_QUEUE_SUSPENDED)) { mq->flags |= MMC_QUEUE_SUSPENDED; _spin_lock_irqsave(q->queue_lock); blk_stop_queue(q); _spin_unlock_irqrestore(q->queue_lock, flags); down(&mq->thread_sem); } }
/** * mmc_queue_resume - resume a previously suspended MMC request queue * @mq: MMC queue to resume */ void mmc_queue_resume(struct mmc_queue *mq) { request_queue_t *q = mq->queue; unsigned long flags; if (mq->flags & MMC_QUEUE_SUSPENDED) { mq->flags &= ~MMC_QUEUE_SUSPENDED; up(&mq->thread_sem); _spin_lock_irqsave(q->queue_lock); blk_start_queue(q); _spin_unlock_irqrestore(q->queue_lock, flags); } }
void mmc_cleanup_queue(struct mmc_queue *mq) { request_queue_t *q = mq->queue; unsigned long flags; /* Mark that we should start throwing out stragglers */ _spin_lock_irqsave(q->queue_lock); q->queuedata = NULL; _spin_unlock_irqrestore(q->queue_lock, flags); /* Then terminate our worker thread */ kthread_stop(mq->thread); kfree(mq->sg); mq->sg = NULL; blk_cleanup_queue(mq->queue); mq->card = NULL; }
static void imxmci_finish_request(struct imxmci_host *host, struct mmc_request *req) { unsigned long flags; _spin_lock_irqsave(&host->lock, flags); host->pending_events &= ~(IMXMCI_PEND_WAIT_RESP_m | IMXMCI_PEND_DMA_END_m | IMXMCI_PEND_DMA_DATA_m | IMXMCI_PEND_CPU_DATA_m); host->imask = IMXMCI_INT_MASK_DEFAULT; MMC_INT_MASK = host->imask; spin_unlock_irqrestore(&host->lock, flags); if(req && req->cmd) host->prev_cmd_code = req->cmd->opcode; host->req = NULL; host->cmd = NULL; host->data = NULL; mmc_request_done(host->mmc, req); }
static void imxmci_start_cmd(struct imxmci_host *host, struct mmc_command *cmd, unsigned int cmdat) { unsigned long flags; u32 imask; WARN_ON(host->cmd != NULL); host->cmd = cmd; /* Ensure, that clock are stopped else command programming and start fails */ imxmci_stop_clock(host); if (cmd->flags & MMC_RSP_BUSY) cmdat |= CMD_DAT_CONT_BUSY; switch (mmc_resp_type(cmd)) { case MMC_RSP_R1: /* short CRC, OPCODE */ case MMC_RSP_R1B:/* short CRC, OPCODE, BUSY */ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R1; break; case MMC_RSP_R2: /* long 136 bit + CRC */ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R2; break; case MMC_RSP_R3: /* short */ cmdat |= CMD_DAT_CONT_RESPONSE_FORMAT_R3; break; default: break; } if ( test_and_clear_bit(IMXMCI_PEND_SET_INIT_b, &host->pending_events) ) cmdat |= CMD_DAT_CONT_INIT; /* This command needs init */ if ( host->actual_bus_width == MMC_BUS_WIDTH_4 ) cmdat |= CMD_DAT_CONT_BUS_WIDTH_4; MMC_CMD = cmd->opcode; MMC_ARGH = cmd->arg >> 16; MMC_ARGL = cmd->arg & 0xffff; MMC_CMD_DAT_CONT = cmdat; atomic_set(&host->stuck_timeout, 0); set_bit(IMXMCI_PEND_WAIT_RESP_b, &host->pending_events); imask = IMXMCI_INT_MASK_DEFAULT; imask &= ~INT_MASK_END_CMD_RES; if ( cmdat & CMD_DAT_CONT_DATA_ENABLE ) { /*imask &= ~INT_MASK_BUF_READY;*/ imask &= ~INT_MASK_DATA_TRAN; if ( cmdat & CMD_DAT_CONT_WRITE ) imask &= ~INT_MASK_WRITE_OP_DONE; if(test_bit(IMXMCI_PEND_CPU_DATA_b, &host->pending_events)) imask &= ~INT_MASK_BUF_READY; } _spin_lock_irqsave(&host->lock, flags); host->imask = imask; MMC_INT_MASK = host->imask; spin_unlock_irqrestore(&host->lock, flags); dev_dbg(mmc_dev(host->mmc), "CMD%02d (0x%02x) mask set to 0x%04x\n", cmd->opcode, cmd->opcode, imask); imxmci_start_clock(host); }