~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to net/wireless/scan.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
93
93
}
94
94
EXPORT_SYMBOL(cfg80211_scan_done);
95
95
 
 
96
void __cfg80211_sched_scan_results(struct work_struct *wk)
 
97
{
 
98
        struct cfg80211_registered_device *rdev;
 
99
 
 
100
        rdev = container_of(wk, struct cfg80211_registered_device,
 
101
                            sched_scan_results_wk);
 
102
 
 
103
        mutex_lock(&rdev->sched_scan_mtx);
 
104
 
 
105
        /* we don't have sched_scan_req anymore if the scan is stopping */
 
106
        if (rdev->sched_scan_req)
 
107
                nl80211_send_sched_scan_results(rdev,
 
108
                                                rdev->sched_scan_req->dev);
 
109
 
 
110
        mutex_unlock(&rdev->sched_scan_mtx);
 
111
}
 
112
 
 
113
void cfg80211_sched_scan_results(struct wiphy *wiphy)
 
114
{
 
115
        /* ignore if we're not scanning */
 
116
        if (wiphy_to_dev(wiphy)->sched_scan_req)
 
117
                queue_work(cfg80211_wq,
 
118
                           &wiphy_to_dev(wiphy)->sched_scan_results_wk);
 
119
}
 
120
EXPORT_SYMBOL(cfg80211_sched_scan_results);
 
121
 
 
122
void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
 
123
{
 
124
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
 
125
 
 
126
        mutex_lock(&rdev->sched_scan_mtx);
 
127
        __cfg80211_stop_sched_scan(rdev, true);
 
128
        mutex_unlock(&rdev->sched_scan_mtx);
 
129
}
 
130
EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
 
131
 
 
132
int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
 
133
                               bool driver_initiated)
 
134
{
 
135
        int err;
 
136
        struct net_device *dev;
 
137
 
 
138
        lockdep_assert_held(&rdev->sched_scan_mtx);
 
139
 
 
140
        if (!rdev->sched_scan_req)
 
141
                return 0;
 
142
 
 
143
        dev = rdev->sched_scan_req->dev;
 
144
 
 
145
        if (!driver_initiated) {
 
146
                err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev);
 
147
                if (err)
 
148
                        return err;
 
149
        }
 
150
 
 
151
        nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED);
 
152
 
 
153
        kfree(rdev->sched_scan_req);
 
154
        rdev->sched_scan_req = NULL;
 
155
 
 
156
        return err;
 
157
}
 
158
 
96
159
static void bss_release(struct kref *ref)
97
160
{
98
161
        struct cfg80211_internal_bss *bss;
124
187
}
125
188
 
126
189
/* must hold dev->bss_lock! */
 
190
static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev,
 
191
                                  struct cfg80211_internal_bss *bss)
 
192
{
 
193
        list_del_init(&bss->list);
 
194
        rb_erase(&bss->rbn, &dev->bss_tree);
 
195
        kref_put(&bss->ref, bss_release);
 
196
}
 
197
 
 
198
/* must hold dev->bss_lock! */
127
199
void cfg80211_bss_expire(struct cfg80211_registered_device *dev)
128
200
{
129
201
        struct cfg80211_internal_bss *bss, *tmp;
134
206
                        continue;
135
207
                if (!time_after(jiffies, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE))
136
208
                        continue;
137
 
                list_del(&bss->list);
138
 
                rb_erase(&bss->rbn, &dev->bss_tree);
139
 
                kref_put(&bss->ref, bss_release);
 
209
                __cfg80211_unlink_bss(dev, bss);
140
210
                expired = true;
141
211
        }
142
212
 
197
267
        return memcmp(ssidie + 2, ssid, ssid_len) == 0;
198
268
}
199
269
 
 
270
static bool is_mesh_bss(struct cfg80211_bss *a)
 
271
{
 
272
        const u8 *ie;
 
273
 
 
274
        if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
 
275
                return false;
 
276
 
 
277
        ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
 
278
                              a->information_elements,
 
279
                              a->len_information_elements);
 
280
        if (!ie)
 
281
                return false;
 
282
 
 
283
        ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
 
284
                              a->information_elements,
 
285
                              a->len_information_elements);
 
286
        if (!ie)
 
287
                return false;
 
288
 
 
289
        return true;
 
290
}
 
291
 
200
292
static bool is_mesh(struct cfg80211_bss *a,
201
293
                    const u8 *meshid, size_t meshidlen,
202
294
                    const u8 *meshcfg)
203
295
{
204
296
        const u8 *ie;
205
297
 
206
 
        if (!is_zero_ether_addr(a->bssid))
 
298
        if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability))
207
299
                return false;
208
300
 
209
301
        ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
241
333
        if (a->channel != b->channel)
242
334
                return b->channel->center_freq - a->channel->center_freq;
243
335
 
244
 
        r = memcmp(a->bssid, b->bssid, ETH_ALEN);
245
 
        if (r)
246
 
                return r;
247
 
 
248
 
        if (is_zero_ether_addr(a->bssid)) {
 
336
        if (is_mesh_bss(a) && is_mesh_bss(b)) {
249
337
                r = cmp_ies(WLAN_EID_MESH_ID,
250
338
                            a->information_elements,
251
339
                            a->len_information_elements,
260
348
                               b->len_information_elements);
261
349
        }
262
350
 
 
351
        r = memcmp(a->bssid, b->bssid, ETH_ALEN);
 
352
        if (r)
 
353
                return r;
 
354
 
263
355
        return cmp_ies(WLAN_EID_SSID,
264
356
                       a->information_elements,
265
357
                       a->len_information_elements,
387
479
                    struct cfg80211_internal_bss *res)
388
480
{
389
481
        struct cfg80211_internal_bss *found = NULL;
390
 
        const u8 *meshid, *meshcfg;
391
482
 
392
483
        /*
393
484
         * The reference to "res" is donated to this function.
400
491
 
401
492
        res->ts = jiffies;
402
493
 
403
 
        if (is_zero_ether_addr(res->pub.bssid)) {
404
 
                /* must be mesh, verify */
405
 
                meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
406
 
                                          res->pub.information_elements,
407
 
                                          res->pub.len_information_elements);
408
 
                meshcfg = cfg80211_find_ie(WLAN_EID_MESH_CONFIG,
409
 
                                           res->pub.information_elements,
410
 
                                           res->pub.len_information_elements);
411
 
                if (!meshid || !meshcfg ||
412
 
                    meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) {
413
 
                        /* bogus mesh */
414
 
                        kref_put(&res->ref, bss_release);
415
 
                        return NULL;
416
 
                }
417
 
        }
418
 
 
419
494
        spin_lock_bh(&dev->bss_lock);
420
495
 
421
496
        found = rb_find_bss(dev, res);
585
660
        struct cfg80211_internal_bss *res;
586
661
        size_t ielen = len - offsetof(struct ieee80211_mgmt,
587
662
                                      u.probe_resp.variable);
588
 
        size_t privsz = wiphy->bss_priv_size;
 
663
        size_t privsz;
 
664
 
 
665
        if (WARN_ON(!mgmt))
 
666
                return NULL;
 
667
 
 
668
        if (WARN_ON(!wiphy))
 
669
                return NULL;
589
670
 
590
671
        if (WARN_ON(wiphy->signal_type == CFG80211_SIGNAL_TYPE_UNSPEC &&
591
672
                    (signal < 0 || signal > 100)))
592
673
                return NULL;
593
674
 
594
 
        if (WARN_ON(!mgmt || !wiphy ||
595
 
                    len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
 
675
        if (WARN_ON(len < offsetof(struct ieee80211_mgmt, u.probe_resp.variable)))
596
676
                return NULL;
597
677
 
 
678
        privsz = wiphy->bss_priv_size;
 
679
 
598
680
        res = kzalloc(sizeof(*res) + privsz + ielen, gfp);
599
681
        if (!res)
600
682
                return NULL;
662
744
 
663
745
        spin_lock_bh(&dev->bss_lock);
664
746
        if (!list_empty(&bss->list)) {
665
 
                list_del_init(&bss->list);
 
747
                __cfg80211_unlink_bss(dev, bss);
666
748
                dev->bss_generation++;
667
 
                rb_erase(&bss->rbn, &dev->bss_tree);
668
 
 
669
 
                kref_put(&bss->ref, bss_release);
670
749
        }
671
750
        spin_unlock_bh(&dev->bss_lock);
672
751
}