Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1919388
  • 博文数量: 376
  • 博客积分: 2147
  • 博客等级: 大尉
  • 技术积分: 3642
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-06 10:47
文章分类

全部博文(376)

文章存档

2019年(3)

2017年(28)

2016年(15)

2015年(17)

2014年(182)

2013年(16)

2012年(115)

我的朋友

分类: 嵌入式

2013-03-22 10:19:20

//drivers/net/gianfar.c
static void free_grp_irqs(struct gfar_priv_grp *grp)
{
#ifdef CONFIG_GFAR_SW_PKT_STEERING
    int i;
    struct gfar_private *priv = grp->priv;
    int cpus = num_online_cpus();

    if (priv->sps) {
        for (i = 0; i < cpus; i++)
            free_irq(grp->msg_virtual_tx[i]->irq, grp);
    }
#endif
    free_irq(grp->interruptError, grp);
#ifndef CONFIG_RX_TX_BD_XNGE
    free_irq(grp->interruptTransmit, grp);
#endif
    free_irq(grp->interruptReceive, grp);
}

void free_irq(unsigned int irq, void *dev_id)
{
    struct irq_desc *desc = irq_to_desc(irq);

    if (!desc)
        return;

    chip_bus_lock(irq, desc);
    kfree(__free_irq(irq, dev_id));
    chip_bus_sync_unlock(irq, desc);
}

static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
{
    struct irq_desc *desc = irq_to_desc(irq);
    struct irqaction *action, **action_ptr;
    unsigned long flags;

    WARN(in_interrupt(), "Trying to free IRQ %d from IRQ context!\n", irq);

    if (!desc)
        return NULL;

    raw_spin_lock_irqsave(&desc->lock, flags);

    /*
     * There can be multiple actions per IRQ descriptor, find the right
     * one based on the dev_id:
     */
    action_ptr = &desc->action;
    for (;;) {
        action = *action_ptr;

        if (!action) {
            WARN(1, "Trying to free already-free IRQ %d\n", irq);
            raw_spin_unlock_irqrestore(&desc->lock, flags);

            return NULL;
        }

        if (action->dev_id == dev_id)//在链表中查找action->dev_id==dev_id的action,对于发送中断,目前实际上链表只有一个元素
            break;
        action_ptr = &action->next;
    }

    /* Found it - now remove it from the list of entries: */
    *action_ptr = action->next;//在链表中删除

    /* Currently used only by UML, might disappear one day: */
#ifdef CONFIG_IRQ_RELEASE_METHOD
    if (desc->chip->release)
        desc->chip->release(irq, dev_id);
#endif

    /* If this was the last handler, shut down the IRQ line: */
    if (!desc->action) {//因为只有一个元素被删除,所以为空
        desc->status |= IRQ_DISABLED;
        if (desc->chip->shutdown)//shutdown为default_shutdown
            desc->chip->shutdown(irq);
        else
            desc->chip->disable(irq);
    }

#ifdef CONFIG_SMP
    /* make sure affinity_hint is cleaned up */
    if (WARN_ON_ONCE(desc->affinity_hint))
        desc->affinity_hint = NULL;
#endif

    raw_spin_unlock_irqrestore(&desc->lock, flags);

    unregister_handler_proc(irq, action);

    /* Make sure it's not being used on another CPU: */
    synchronize_irq(irq);

#ifdef CONFIG_DEBUG_SHIRQ
    /*
     * It's a shared IRQ -- the driver ought to be prepared for an IRQ
     * event to happen even now it's being freed, so let's make sure that
     * is so by doing an extra call to the handler ....
     *
     * ( We do this after actually deregistering it, to make sure that a
     *   'real' IRQ doesn't run in * parallel with our fake. )
     */
    if (action->flags & IRQF_SHARED) {
        local_irq_save(flags);
        action->handler(irq, dev_id);
        local_irq_restore(flags);
    }
#endif

    if (action->thread) {
        if (!test_bit(IRQTF_DIED, &action->thread_flags))
            kthread_stop(action->thread);
        put_task_struct(action->thread);
    }

    return action;
}

static void default_shutdown(unsigned int irq)
{
    struct irq_desc *desc = irq_to_desc(irq);

    desc->chip->mask(irq);//调用mpic_irq_chip的mpic_mask_irq
    desc->status |= IRQ_MASKED;
}

void mpic_mask_irq(unsigned int irq)
{
    unsigned int loops = 100000;
    struct mpic *mpic = mpic_from_irq(irq);
    unsigned int src = mpic_irq_to_hw(irq);

    DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);

    mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
               mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
               MPIC_VECPRI_MASK);//设置屏蔽位

    /* make sure mask gets to controller before we return to user */
    do {
        if (!loops--) {
            printk(KERN_ERR "mpic_enable_irq timeout\n");
            break;
        }
    } while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
}
阅读(2912) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~