madwifi-ng: add workaround for high interrupt latency (fixes picture dropouts on...
[opendreambox.git] / meta-opendreambox / recipes-connectivity / madwifi / files / workaround-high-interrupt-latency.patch
1 --- madwifi-ng-r3314-20080131.org/net80211/ieee80211_scan.c     2012-08-06 22:13:42.000000000 +0200
2 +++ madwifi-ng-r3314-20080131/net80211/ieee80211_scan.c 2012-08-08 22:38:46.518295928 +0200
3 @@ -47,6 +47,13 @@
4  #include <linux/etherdevice.h>
5  #include <linux/random.h>
6  #include <linux/interrupt.h>
7 +
8 +#define USE_WORKQUEUE
9 +
10 +#ifdef USE_WORKQUEUE
11 +#include <linux/workqueue.h>
12 +#endif
13 +
14  #include <linux/delay.h>
15  
16  #include "if_media.h"
17 @@ -67,6 +74,9 @@
18         u_int ss_duration;                      /* duration for next scan */
19         struct tasklet_struct ss_pwrsav;        /* sta ps ena tasklet */
20         struct timer_list ss_scan_timer;        /* scan timer */
21 +#ifdef USE_WORKQUEUE
22 +       struct work_struct scan_next_work;
23 +#endif
24  };
25  #define        SCAN_PRIVATE(ss)        ((struct scan_state *) ss)
26  
27 @@ -96,8 +106,14 @@
28  
29  static void scan_restart_pwrsav(unsigned long);
30  static void scan_next(unsigned long);
31 +#ifdef USE_WORKQUEUE
32 +static void scan_next_timer(unsigned long);
33 +static void scan_next_work_cb(struct work_struct *work);
34 +static struct workqueue_struct *scan_wq;
35 +#endif
36  
37  DEFINE_SPINLOCK(channel_lock);
38 +EXPORT_SYMBOL(channel_lock);
39  static LIST_HEAD(channels_inuse);
40  
41  struct channel_inuse {
42 @@ -224,9 +238,16 @@
43         MALLOC(ss, struct scan_state *, sizeof(struct scan_state),
44                 M_80211_SCAN, M_NOWAIT | M_ZERO);
45         if (ss != NULL) {
46 +               if (!scan_wq)
47 +                       scan_wq = alloc_workqueue("madwifi_scan", 0, 1);
48                 init_timer(&ss->ss_scan_timer);
49 -               ss->ss_scan_timer.function = scan_next;
50                 ss->ss_scan_timer.data = (unsigned long) ss;
51 +#ifdef USE_WORKQUEUE
52 +               ss->ss_scan_timer.function = scan_next_timer;
53 +               INIT_WORK(&ss->scan_next_work, scan_next_work_cb);
54 +#else
55 +               ss->ss_scan_timer.function = scan_next;
56 +#endif
57                 tasklet_init(&ss->ss_pwrsav, scan_restart_pwrsav,
58                         (unsigned long) ss);
59                 ic->ic_scan = &ss->base;
60 @@ -241,6 +262,9 @@
61  
62         if (ss != NULL) {
63                 del_timer(&SCAN_PRIVATE(ss)->ss_scan_timer);
64 +#ifdef USE_WORKQUEUE
65 +               flush_workqueue(scan_wq);
66 +#endif
67                 tasklet_kill(&SCAN_PRIVATE(ss)->ss_pwrsav);
68                 if (ss->ss_ops != NULL) {
69                         ss->ss_ops->scan_detach(ss);
70 @@ -276,6 +300,9 @@
71         if (ss->ss_vap == vap) {
72                 if (ic->ic_flags & IEEE80211_F_SCAN) {
73                         del_timer(&SCAN_PRIVATE(ss)->ss_scan_timer);
74 +#ifdef USE_WORKQUEUE
75 +                       flush_workqueue(scan_wq);
76 +#endif
77                         ic->ic_flags &= ~IEEE80211_F_SCAN;
78                 }
79                 if (ss->ss_ops != NULL) {
80 @@ -911,6 +938,21 @@
81  #undef ISCAN_REP
82  }
83  
84 +#ifdef USE_WORKQUEUE
85 +static void
86 +scan_next_timer(unsigned long arg)
87 +{
88 +       struct scan_state *ss = (struct scan_state *) arg;
89 +       queue_work_on(1, scan_wq, &ss->scan_next_work);
90 +}
91 +
92 +static void scan_next_work_cb(struct work_struct *work)
93 +{
94 +       struct scan_state *s = container_of(work, struct scan_state, scan_next_work);
95 +       scan_next((unsigned long)s);
96 +}
97 +#endif
98 +
99  #ifdef IEEE80211_DEBUG
100  static void
101  dump_probe_beacon(u_int8_t subtype, int isnew,