sdio_irq_thread对中断的模拟

对于不支持SDIO 中断的host,kerne会采用polling的方式来实现伪中断:不断的唤醒ksdioirqd来检查SDIO的CCCR的中断标志位。(支持SDIO中断的host,则直接在SDIO中断产生的时候由host的驱动来负责通知mmc子系统唤醒ksdioirqd来检查中断).

ksdioirqd的关键性代码如下。

do {
        /*
         * We claim the host here on drivers behalf for a couple
         * reasons:
         *
         * 1) it is already needed to retrieve the CCCR_INTx;
         * 2) we want the driver(s) to clear the IRQ condition ASAP;
         * 3) we need to control the abort condition locally.
         *
         * Just like traditional hard IRQ handlers, we expect SDIO
         * IRQ handlers to be quick and to the point, so that the
         * holding of the host lock does not cover too much work
         * that doesn't require that lock to be held.
         */
        ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort);
        if (ret)
            break;
        ret = process_sdio_pending_irqs(host->card);  //检查是否有任何中断
        mmc_release_host(host);

        /*
         * Give other threads a chance to run in the presence of
         * errors.
         */
        if (ret < 0) {
            set_current_state(TASK_INTERRUPTIBLE);
            if (!kthread_should_stop())
                schedule_timeout(HZ);
            set_current_state(TASK_RUNNING);
        }

        /*
         * Adaptive polling frequency based on the assumption
         * that an interrupt will be closely followed by more.
         * This has a substantial benefit for network devices.
         */
        if (!(host->caps & MMC_CAP_SDIO_IRQ)) {
            if (ret > 0)
                period /= 2;
            else {    //如果有中断产生则将唤醒的时间间隔减半,否则的话不断的加大唤醒间隔直到最大。
                period++;   //这种方式很类似于高性能网卡驱动中使用的polling于int结合的方式。

                if (period > idle_period) //在有中断产生的时候产生polling,一旦polling检查到没有中断就
                    period = idle_period;//改成中断模式(int)
            }
        }

        set_current_state(TASK_INTERRUPTIBLE);
        if (host->caps & MMC_CAP_SDIO_IRQ)
            host->ops->enable_sdio_irq(host, 1);
        if (!kthread_should_stop())
            schedule_timeout(period);
        set_current_state(TASK_RUNNING);
    } while (!kthread_should_stop());

你可能感兴趣的:(thread)