aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorScott James Remnant <keybuk@google.com>2011-03-08 13:45:30 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-03-09 16:10:57 -0500
commit4d9d88d121fdd01dd859717909ea3c90173f143a (patch)
tree46f08bf9ab7c84a0978d3bc5a6202b0af15a308a /net/wireless
parent80751e2b8ffcbbe065e850d943301aa1ab219599 (diff)
net/wireless: add COUNTRY to to regulatory device uevent
Regulatory devices issue change uevents to inform userspace of a need to call the crda tool; however these can often be sent before udevd is running, and were not previously included in the results of udevadm trigger (which requests a new change event using the /uevent attribute of the sysfs object). Add a uevent function to the device type which includes the COUNTRY information from the last request if it has yet to be processed, the case of multiple requests is already handled in the code by checking whether an unprocessed one is queued in the same manner and refusing to queue a new one. The existing udev rule continues to work as before. Signed-off-by: Scott James Remnant <keybuk@google.com> Acked-By: Kay Sievers <kay.sievers@vrfy.org> Acked-by: Greg Kroah-Hartman <gregkh@suse.de> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/reg.c39
-rw-r--r--net/wireless/reg.h1
2 files changed, 29 insertions, 11 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index c565689f0b9f..3332d5bce317 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -63,6 +63,10 @@ static struct regulatory_request *last_request;
63/* To trigger userspace events */ 63/* To trigger userspace events */
64static struct platform_device *reg_pdev; 64static struct platform_device *reg_pdev;
65 65
66static struct device_type reg_device_type = {
67 .uevent = reg_device_uevent,
68};
69
66/* 70/*
67 * Central wireless core regulatory domains, we only need two, 71 * Central wireless core regulatory domains, we only need two,
68 * the current one and a world regulatory domain in case we have no 72 * the current one and a world regulatory domain in case we have no
@@ -362,16 +366,11 @@ static inline void reg_regdb_query(const char *alpha2) {}
362 366
363/* 367/*
364 * This lets us keep regulatory code which is updated on a regulatory 368 * This lets us keep regulatory code which is updated on a regulatory
365 * basis in userspace. 369 * basis in userspace. Country information is filled in by
370 * reg_device_uevent
366 */ 371 */
367static int call_crda(const char *alpha2) 372static int call_crda(const char *alpha2)
368{ 373{
369 char country_env[9 + 2] = "COUNTRY=";
370 char *envp[] = {
371 country_env,
372 NULL
373 };
374
375 if (!is_world_regdom((char *) alpha2)) 374 if (!is_world_regdom((char *) alpha2))
376 pr_info("Calling CRDA for country: %c%c\n", 375 pr_info("Calling CRDA for country: %c%c\n",
377 alpha2[0], alpha2[1]); 376 alpha2[0], alpha2[1]);
@@ -381,10 +380,7 @@ static int call_crda(const char *alpha2)
381 /* query internal regulatory database (if it exists) */ 380 /* query internal regulatory database (if it exists) */
382 reg_regdb_query(alpha2); 381 reg_regdb_query(alpha2);
383 382
384 country_env[8] = alpha2[0]; 383 return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
385 country_env[9] = alpha2[1];
386
387 return kobject_uevent_env(&reg_pdev->dev.kobj, KOBJ_CHANGE, envp);
388} 384}
389 385
390/* Used by nl80211 before kmalloc'ing our regulatory domain */ 386/* Used by nl80211 before kmalloc'ing our regulatory domain */
@@ -2087,6 +2083,25 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2087 return r; 2083 return r;
2088} 2084}
2089 2085
2086#ifdef CONFIG_HOTPLUG
2087int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
2088{
2089 if (last_request && !last_request->processed) {
2090 if (add_uevent_var(env, "COUNTRY=%c%c",
2091 last_request->alpha2[0],
2092 last_request->alpha2[1]))
2093 return -ENOMEM;
2094 }
2095
2096 return 0;
2097}
2098#else
2099int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)
2100{
2101 return -ENODEV;
2102}
2103#endif /* CONFIG_HOTPLUG */
2104
2090/* Caller must hold cfg80211_mutex */ 2105/* Caller must hold cfg80211_mutex */
2091void reg_device_remove(struct wiphy *wiphy) 2106void reg_device_remove(struct wiphy *wiphy)
2092{ 2107{
@@ -2118,6 +2133,8 @@ int __init regulatory_init(void)
2118 if (IS_ERR(reg_pdev)) 2133 if (IS_ERR(reg_pdev))
2119 return PTR_ERR(reg_pdev); 2134 return PTR_ERR(reg_pdev);
2120 2135
2136 reg_pdev->dev.type = &reg_device_type;
2137
2121 spin_lock_init(&reg_requests_lock); 2138 spin_lock_init(&reg_requests_lock);
2122 spin_lock_init(&reg_pending_beacons_lock); 2139 spin_lock_init(&reg_pending_beacons_lock);
2123 2140
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index c4695d07af23..b67d1c3a2fb9 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -8,6 +8,7 @@ bool reg_is_valid_request(const char *alpha2);
8 8
9int regulatory_hint_user(const char *alpha2); 9int regulatory_hint_user(const char *alpha2);
10 10
11int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env);
11void reg_device_remove(struct wiphy *wiphy); 12void reg_device_remove(struct wiphy *wiphy);
12 13
13int __init regulatory_init(void); 14int __init regulatory_init(void);