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

« back to all changes in this revision

Viewing changes to net/wireless/reg.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:
63
63
/* To trigger userspace events */
64
64
static struct platform_device *reg_pdev;
65
65
 
 
66
static struct device_type reg_device_type = {
 
67
        .uevent = reg_device_uevent,
 
68
};
 
69
 
66
70
/*
67
71
 * Central wireless core regulatory domains, we only need two,
68
72
 * the current one and a world regulatory domain in case we have no
102
106
static void reg_todo(struct work_struct *work);
103
107
static DECLARE_WORK(reg_work, reg_todo);
104
108
 
 
109
static void reg_timeout_work(struct work_struct *work);
 
110
static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work);
 
111
 
105
112
/* We keep a static world regulatory domain in case of the absence of CRDA */
106
113
static const struct ieee80211_regdomain world_regdom = {
107
114
        .n_reg_rules = 5,
362
369
 
363
370
/*
364
371
 * This lets us keep regulatory code which is updated on a regulatory
365
 
 * basis in userspace.
 
372
 * basis in userspace. Country information is filled in by
 
373
 * reg_device_uevent
366
374
 */
367
375
static int call_crda(const char *alpha2)
368
376
{
369
 
        char country_env[9 + 2] = "COUNTRY=";
370
 
        char *envp[] = {
371
 
                country_env,
372
 
                NULL
373
 
        };
374
 
 
375
377
        if (!is_world_regdom((char *) alpha2))
376
378
                pr_info("Calling CRDA for country: %c%c\n",
377
379
                        alpha2[0], alpha2[1]);
381
383
        /* query internal regulatory database (if it exists) */
382
384
        reg_regdb_query(alpha2);
383
385
 
384
 
        country_env[8] = alpha2[0];
385
 
        country_env[9] = alpha2[1];
386
 
 
387
 
        return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, envp);
 
386
        return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
388
387
}
389
388
 
390
389
/* Used by nl80211 before kmalloc'ing our regulatory domain */
673
672
        for (i = 0; i < regd->n_reg_rules; i++) {
674
673
                const struct ieee80211_reg_rule *rr;
675
674
                const struct ieee80211_freq_range *fr = NULL;
676
 
                const struct ieee80211_power_rule *pr = NULL;
677
675
 
678
676
                rr = &regd->reg_rules[i];
679
677
                fr = &rr->freq_range;
680
 
                pr = &rr->power_rule;
681
678
 
682
679
                /*
683
680
                 * We only need to know if one frequency rule was
813
810
        if (r) {
814
811
                /*
815
812
                 * We will disable all channels that do not match our
816
 
                 * recieved regulatory rule unless the hint is coming
 
813
                 * received regulatory rule unless the hint is coming
817
814
                 * from a Country IE and the Country IE had no information
818
815
                 * about a band. The IEEE 802.11 spec allows for an AP
819
816
                 * to send only a subset of the regulatory rules allowed,
842
839
            request_wiphy && request_wiphy == wiphy &&
843
840
            request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
844
841
                /*
845
 
                 * This gaurantees the driver's requested regulatory domain
 
842
                 * This guarantees the driver's requested regulatory domain
846
843
                 * will always be used as a base for further regulatory
847
844
                 * settings
848
845
                 */
1334
1331
                need_more_processing = true;
1335
1332
        spin_unlock(&reg_requests_lock);
1336
1333
 
 
1334
        if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
 
1335
                cancel_delayed_work_sync(&reg_timeout);
 
1336
 
1337
1337
        if (need_more_processing)
1338
1338
                schedule_work(&reg_work);
1339
1339
}
1444
1444
        r = __regulatory_hint(wiphy, reg_request);
1445
1445
        /* This is required so that the orig_* parameters are saved */
1446
1446
        if (r == -EALREADY && wiphy &&
1447
 
            wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
 
1447
            wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
1448
1448
                wiphy_update_regulatory(wiphy, initiator);
 
1449
                return;
 
1450
        }
 
1451
 
 
1452
        /*
 
1453
         * We only time out user hints, given that they should be the only
 
1454
         * source of bogus requests.
 
1455
         */
 
1456
        if (r != -EALREADY &&
 
1457
            reg_request->initiator == NL80211_REGDOM_SET_BY_USER)
 
1458
                schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
1449
1459
}
1450
1460
 
1451
1461
/*
1748
1758
{
1749
1759
        char alpha2[2];
1750
1760
        struct reg_beacon *reg_beacon, *btmp;
 
1761
        struct regulatory_request *reg_request, *tmp;
 
1762
        LIST_HEAD(tmp_reg_req_list);
1751
1763
 
1752
1764
        mutex_lock(&cfg80211_mutex);
1753
1765
        mutex_lock(&reg_mutex);
1755
1767
        reset_regdomains();
1756
1768
        restore_alpha2(alpha2, reset_user);
1757
1769
 
 
1770
        /*
 
1771
         * If there's any pending requests we simply
 
1772
         * stash them to a temporary pending queue and
 
1773
         * add then after we've restored regulatory
 
1774
         * settings.
 
1775
         */
 
1776
        spin_lock(&reg_requests_lock);
 
1777
        if (!list_empty(&reg_requests_list)) {
 
1778
                list_for_each_entry_safe(reg_request, tmp,
 
1779
                                         &reg_requests_list, list) {
 
1780
                        if (reg_request->initiator !=
 
1781
                            NL80211_REGDOM_SET_BY_USER)
 
1782
                                continue;
 
1783
                        list_del(&reg_request->list);
 
1784
                        list_add_tail(&reg_request->list, &tmp_reg_req_list);
 
1785
                }
 
1786
        }
 
1787
        spin_unlock(&reg_requests_lock);
 
1788
 
1758
1789
        /* Clear beacon hints */
1759
1790
        spin_lock_bh(&reg_pending_beacons_lock);
1760
1791
        if (!list_empty(&reg_pending_beacons)) {
1789
1820
         */
1790
1821
        if (is_an_alpha2(alpha2))
1791
1822
                regulatory_hint_user(user_alpha2);
 
1823
 
 
1824
        if (list_empty(&tmp_reg_req_list))
 
1825
                return;
 
1826
 
 
1827
        mutex_lock(&cfg80211_mutex);
 
1828
        mutex_lock(&reg_mutex);
 
1829
 
 
1830
        spin_lock(&reg_requests_lock);
 
1831
        list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) {
 
1832
                REG_DBG_PRINT("Adding request for country %c%c back "
 
1833
                              "into the queue\n",
 
1834
                              reg_request->alpha2[0],
 
1835
                              reg_request->alpha2[1]);
 
1836
                list_del(&reg_request->list);
 
1837
                list_add_tail(&reg_request->list, &reg_requests_list);
 
1838
        }
 
1839
        spin_unlock(&reg_requests_lock);
 
1840
 
 
1841
        mutex_unlock(&reg_mutex);
 
1842
        mutex_unlock(&cfg80211_mutex);
 
1843
 
 
1844
        REG_DBG_PRINT("Kicking the queue\n");
 
1845
 
 
1846
        schedule_work(&reg_work);
1792
1847
}
1793
1848
 
1794
 
 
1795
1849
void regulatory_hint_disconnect(void)
1796
1850
{
1797
1851
        REG_DBG_PRINT("All devices are disconnected, going to "
1801
1855
 
1802
1856
static bool freq_is_chan_12_13_14(u16 freq)
1803
1857
{
1804
 
        if (freq == ieee80211_channel_to_frequency(12) ||
1805
 
            freq == ieee80211_channel_to_frequency(13) ||
1806
 
            freq == ieee80211_channel_to_frequency(14))
 
1858
        if (freq == ieee80211_channel_to_frequency(12, IEEE80211_BAND_2GHZ) ||
 
1859
            freq == ieee80211_channel_to_frequency(13, IEEE80211_BAND_2GHZ) ||
 
1860
            freq == ieee80211_channel_to_frequency(14, IEEE80211_BAND_2GHZ))
1807
1861
                return true;
1808
1862
        return false;
1809
1863
}
2087
2141
        return r;
2088
2142
}
2089
2143
 
 
2144
#ifdef CONFIG_HOTPLUG
 
2145
int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 
2146
{
 
2147
        if (last_request && !last_request->processed) {
 
2148
                if (add_uevent_var(env, "COUNTRY=%c%c",
 
2149
                                   last_request->alpha2[0],
 
2150
                                   last_request->alpha2[1]))
 
2151
                        return -ENOMEM;
 
2152
        }
 
2153
 
 
2154
        return 0;
 
2155
}
 
2156
#else
 
2157
int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 
2158
{
 
2159
        return -ENODEV;
 
2160
}
 
2161
#endif /* CONFIG_HOTPLUG */
 
2162
 
2090
2163
/* Caller must hold cfg80211_mutex */
2091
2164
void reg_device_remove(struct wiphy *wiphy)
2092
2165
{
2110
2183
        mutex_unlock(&reg_mutex);
2111
2184
}
2112
2185
 
 
2186
static void reg_timeout_work(struct work_struct *work)
 
2187
{
 
2188
        REG_DBG_PRINT("Timeout while waiting for CRDA to reply, "
 
2189
                      "restoring regulatory settings");
 
2190
        restore_regulatory_settings(true);
 
2191
}
 
2192
 
2113
2193
int __init regulatory_init(void)
2114
2194
{
2115
2195
        int err = 0;
2118
2198
        if (IS_ERR(reg_pdev))
2119
2199
                return PTR_ERR(reg_pdev);
2120
2200
 
 
2201
        reg_pdev->dev.type = &reg_device_type;
 
2202
 
2121
2203
        spin_lock_init(&reg_requests_lock);
2122
2204
        spin_lock_init(&reg_pending_beacons_lock);
2123
2205
 
2161
2243
        struct reg_beacon *reg_beacon, *btmp;
2162
2244
 
2163
2245
        cancel_work_sync(&reg_work);
 
2246
        cancel_delayed_work_sync(&reg_timeout);
2164
2247
 
2165
2248
        mutex_lock(&cfg80211_mutex);
2166
2249
        mutex_lock(&reg_mutex);