static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct sh_mmcif_host *host = mmc_priv(mmc); switch (mrq->cmd->opcode) { /* MMCIF does not support SD/SDIO command */ case SD_IO_SEND_OP_COND: case MMC_APP_CMD: mrq->cmd->error = -ETIMEDOUT; mmc_request_done(mmc, mrq); return; case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */ if (!mrq->data) { /* send_if_cond cmd (not support) */ mrq->cmd->error = -ETIMEDOUT; mmc_request_done(mmc, mrq); return; } break; default: break; } host->data = mrq->data; sh_mmcif_start_cmd(host, mrq, mrq->cmd); host->data = NULL; if (mrq->cmd->error != 0) { mmc_request_done(mmc, mrq); return; } if (mrq->stop) sh_mmcif_stop_cmd(host, mrq, mrq->stop); mmc_request_done(mmc, mrq); }
static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) { struct sh_mmcif_host *host = dev_id; struct mmc_request *mrq; bool wait = false; cancel_delayed_work_sync(&host->timeout_work); mutex_lock(&host->thread_lock); mrq = host->mrq; if (!mrq) { dev_dbg(&host->pd->dev, "IRQ thread state %u, wait %u: NULL mrq!\n", host->state, host->wait_for); mutex_unlock(&host->thread_lock); return IRQ_HANDLED; } /* * All handlers return true, if processing continues, and false, if the * request has to be completed - successfully or not */ switch (host->wait_for) { case MMCIF_WAIT_FOR_REQUEST: /* We're too late, the timeout has already kicked in */ mutex_unlock(&host->thread_lock); return IRQ_HANDLED; case MMCIF_WAIT_FOR_CMD: /* Wait for data? */ wait = sh_mmcif_end_cmd(host); break; case MMCIF_WAIT_FOR_MREAD: /* Wait for more data? */ wait = sh_mmcif_mread_block(host); break; case MMCIF_WAIT_FOR_READ: /* Wait for data end? */ wait = sh_mmcif_read_block(host); break; case MMCIF_WAIT_FOR_MWRITE: /* Wait data to write? */ wait = sh_mmcif_mwrite_block(host); break; case MMCIF_WAIT_FOR_WRITE: /* Wait for data end? */ wait = sh_mmcif_write_block(host); break; case MMCIF_WAIT_FOR_STOP: if (host->sd_error) { mrq->stop->error = sh_mmcif_error_manage(host); dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, mrq->stop->error); break; } sh_mmcif_get_cmd12response(host, mrq->stop); mrq->stop->error = 0; break; case MMCIF_WAIT_FOR_READ_END: case MMCIF_WAIT_FOR_WRITE_END: if (host->sd_error) { mrq->data->error = sh_mmcif_error_manage(host); dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, mrq->data->error); } break; default: BUG(); } if (wait) { schedule_delayed_work(&host->timeout_work, host->timeout); /* Wait for more data */ mutex_unlock(&host->thread_lock); return IRQ_HANDLED; } if (host->wait_for != MMCIF_WAIT_FOR_STOP) { struct mmc_data *data = mrq->data; if (!mrq->cmd->error && data && !data->error) data->bytes_xfered = data->blocks * data->blksz; if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) { sh_mmcif_stop_cmd(host, mrq); if (!mrq->stop->error) { schedule_delayed_work(&host->timeout_work, host->timeout); mutex_unlock(&host->thread_lock); return IRQ_HANDLED; } } } host->wait_for = MMCIF_WAIT_FOR_REQUEST; host->state = STATE_IDLE; host->mrq = NULL; mmc_request_done(host->mmc, mrq); mutex_unlock(&host->thread_lock); return IRQ_HANDLED; }