zoukankan      html  css  js  c++  java
  • atheros无线驱动之:数据接收流程

    1:数据处理函数tasklet,workqueue
    在之前的初始化代码中的函数__ath_attach()中,有如下的代码:

    #ifndef ATH_SUPPORT_HTC
    #ifdef ADF_SUPPORT
        ATH_INIT_TQUEUE(&osdev->intr_tq, (adf_os_defer_fn_t)ath_tasklet, (void*)dev);
    #else
       ATH_INIT_TQUEUE(&osdev->intr_tq, ath_tasklet, dev);
    #endif
    #endif

    首先开看看 ATH_INIT_TQUEUE()是怎么定义的:
    #ifdef DECLARE_TASKLET          /* native tasklets */
    #define tq_struct tasklet_struct
    #define ATH_INIT_TQUEUE(a,b,c)      tasklet_init((a),(b),(unsigned long)(c))
    #define ATH_SCHEDULE_TQUEUE(a,b)    tasklet_schedule((a))
    typedef unsigned long TQUEUE_ARG;
    #define mark_bh(a)
    #else                   /* immediate work queue */
    #define ATH_INIT_TQUEUE(a,b,c)      INIT_TQUEUE(a,b,c)
    #define ATH_SCHEDULE_TQUEUE(a,b) do {      
        *(b) |= queue_task((a), &tq_immediate);
    } while(0)
    typedef void *TQUEUE_ARG;
    #define tasklet_disable(t)  do { (void) t; local_bh_disable(); } while (0)
    #define tasklet_enable(t)   do { (void) t; local_bh_enable(); } while (0)
    #endif /* !DECLARE_TASKLET */
    有上面的定义可以知道:次数定义的是中断处理函数的下半部,其实现采用俩种方式:tasklet和work_queue。
    在中断处理函数中将会调用task或者queue的调度函数即上面定义的:ATH_SCHEDULE_TQUEUE
    函数ath_tasklet()定义如下:
    static void ath_tasklet(TQUEUE_ARG data)
    {
        struct net_device *dev = (struct net_device *)data;
        struct ath_softc_net80211 *scn = ath_netdev_priv(dev);
        do_ath_handle_intr(scn->sc_dev);
    }
    #define do_ath_handle_intr(_dev) do{ ath_handle_intr_generic(_dev);}while(0)
    #define ath_handle_intr_generic(_dev)   scn->sc_ops->handle_intr(_dev) 

    static const struct ath_ops ath_ar_ops = {
        ath_handle_intr,            /* handle_intr */
        ath_rx_tasklet,             /* rx_proc */

    }
    2:中断的申请
    在__ath_attach()有如下中断申请代码
    #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
        if (request_irq(dev->irq, ath_isr, SA_SHIRQ, dev->name, dev)) {
    #else
    #ifdef ATH_AHB
        if (request_irq(dev->irq, ath_isr, IRQF_DISABLED, dev->name, dev)) {
    #else
        if (request_irq(dev->irq, ath_isr, IRQF_SHARED, dev->name, dev)) {
    #endif
    #endif
            printk(KERN_WARNING "%s: request_irq failed ", dev->name);
            error = -EIO;
            goto bad3;
        }  由此可知,中断处理函数为:
    ath_isr(int irq, void *dev_id, struct pt_regs *regs)
    {
        do_ath_isr(irq,dev_id,regs);
    }
    #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
    #define do_ath_isr(_irq,_dev_id) do{ return ath_isr_generic(_irq,_dev_id);}while(0)
    #else
    #define do_ath_isr(_irq,_dev_id,_regs) do{ returnath_isr_generic(_irq,_dev_id,_regs);}while(0)
    #endif //if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)

    irqreturn_t ath_isr_generic(int irq, void *dev_id, struct pt_regs *regs)
    #endif
    {
        struct net_device *dev = dev_id;
        struct ath_softc_net80211 *scn = ath_netdev_priv(dev);
        int sched, needmark = 0;
        /* always acknowledge the interrupt */
        sched = scn->sc_ops->isr(scn->sc_dev);
        switch(sched)
        {
        case ATH_ISR_NOSCHED:
            return  IRQ_HANDLED;
            
        case ATH_ISR_NOTMINE:
            return IRQ_NONE;
            
        default:
            if ((dev->flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP))
            {
                DPRINTF_INTSAFE(scn, ATH_DEBUG_INTR, "%s: flags 0x%x ", __func__, dev->flags);
                scn->sc_ops->disable_interrupt(scn->sc_dev);     /* disable further intr's */
                return IRQ_HANDLED;
            }
        }
        
        /*
        ** See if the transmit queue processing needs to be scheduled
        */
        
        ATH_SCHEDULE_TQUEUE(&scn->sc_osdev->intr_tq, &needmark);
        if (needmark)
            mark_bh(IMMEDIATE_BH);
        return IRQ_HANDLED;
    }上面已经说明了在中断处理函数中对tasklet或者workqueue的调度。
    3:代码执行流程

    其代码执行过程如下:




    当数据数据之后,会交给函数ieee80211_input(),在测函数中会处理80211的三大数据包类似,数据帧,管理帧和控制帧。

  • 相关阅读:
    [leetcode-671-Second Minimum Node In a Binary Tree]
    [leetcode-667-Beautiful Arrangement II]
    棋盘从左上到右下最小初始值
    [leetcode-666-Path Sum IV]
    [leetcode-665-Non-decreasing Array]
    [leetcode-215-Kth Largest Element in an Array]
    LINQ简记(3):子句
    技巧篇:如何重写基类的事件
    技巧篇:结合反射技术实现多算法动态加密
    龙年新作:水印文字添加工具源码摘要
  • 原文地址:https://www.cnblogs.com/jackyzzy/p/4260997.html
Copyright © 2011-2022 走看看