예제 #1
0
/**
 * 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);
	}
}
예제 #2
0
/**
 * 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);
	}
}
예제 #3
0
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;
}
예제 #4
0
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);
}
예제 #5
0
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);
}