2010-05-27 16:19:22

by Lukáš Turek

[permalink] [raw]
Subject: Regulatory problem with multiple wireless interfaces

Hi,

I reported this first in ath5k-devel, but now I'm convinced the problem lies
in the cfg80211 regulatory framework.

When there is more than one wireless card installed, sometimes the CRDA reply
for first detected card's request gets into the kernel before next card is
requested and everything is fine. But sometimes CRDA replies too late and
kernel sends multiple request, one for each card. The behavior is completely
random, different every boot.

This is dmesg output from a system with three AR5414 PCI cards, all with
regdomain 0x36 (Czech Republic) exhibiting this problem:

ath5k 0000:02:01.0: PCI INT A -> GSI 22 (level, low) -> IRQ 22
ath5k 0000:02:01.0: registered as 'phy0'
ath: EEPROM regdomain: 0x36
ath: EEPROM indicates we should expect a direct regpair map
ath: Country alpha2 being used: CZ
ath: Regpair used: 0x36
udev: renamed network interface eth0 to eth2
udev: renamed network interface eth1_rename to eth0
phy0: Selected rate control algorithm 'minstrel'
ath5k phy0: Atheros AR5414 chip found (MAC: 0xa5, PHY: 0x61)
ath5k 0000:02:02.0: PCI INT A -> GSI 17 (level, low) -> IRQ 17
ath5k 0000:02:02.0: registered as 'phy1'
ath: EEPROM regdomain: 0x36
ath: EEPROM indicates we should expect a direct regpair map
ath: Country alpha2 being used: CZ
ath: Regpair used: 0x36
cfg80211: Calling CRDA for country: CZ
phy1: Selected rate control algorithm 'minstrel'
ath5k phy1: Atheros AR5414 chip found (MAC: 0xa5, PHY: 0x61)
ath5k 0000:02:03.0: PCI INT A -> GSI 19 (level, low) -> IRQ 19
ath5k 0000:02:03.0: registered as 'phy2'
ath: EEPROM regdomain: 0x36
ath: EEPROM indicates we should expect a direct regpair map
ath: Country alpha2 being used: CZ
ath: Regpair used: 0x36
cfg80211: Calling CRDA for country: CZ
udev: renamed network interface wlan1 to wlan3
phy2: Selected rate control algorithm 'minstrel'
ath5k phy2: Atheros AR5414 chip found (MAC: 0xa5, PHY: 0x61)
cfg80211: Calling CRDA for country: CZ
udev: renamed network interface wlan1 to wlan2
cfg80211: Current regulatory domain intersected:
(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
(2402000 KHz - 2472000 KHz @ 40000 KHz), (N/A, 2000 mBm)
(2457000 KHz - 2482000 KHz @ 20000 KHz), (N/A, 2000 mBm)
(2474000 KHz - 2483500 KHz @ 9500 KHz), (N/A, 2000 mBm)
(5170000 KHz - 5250000 KHz @ 40000 KHz), (N/A, 2000 mBm)
cfg80211: Current regulatory domain intersected:
(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
(2402000 KHz - 2472000 KHz @ 40000 KHz), (N/A, 2000 mBm)
(2457000 KHz - 2482000 KHz @ 20000 KHz), (N/A, 2000 mBm)
(2474000 KHz - 2483500 KHz @ 9500 KHz), (N/A, 2000 mBm)
(5170000 KHz - 5250000 KHz @ 40000 KHz), (N/A, 2000 mBm)
cfg80211: Current regulatory domain intersected:
(start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)
(2402000 KHz - 2472000 KHz @ 40000 KHz), (N/A, 2000 mBm)
(2457000 KHz - 2482000 KHz @ 20000 KHz), (N/A, 2000 mBm)
(2474000 KHz - 2483500 KHz @ 9500 KHz), (N/A, 2000 mBm)
(5170000 KHz - 5250000 KHz @ 40000 KHz), (N/A, 2000 mBm)

The result is that all but the last card stay in world regdomain with channels
100-140 unavailable. Only the last card has correct channels enabled. I had
to disable some code at 4 places to get it working, so there might be mutiple
bugs, or they all have some common cause, but I couldn't find any. The ugly
patch I used is attached, hopefully it will provide some pointers to find out
what's wrong.

My guess is that the main problem is the use of the global variable
last_request, which is incompatible with asynchronous replies from CRDA.

Unfortunately it's quite hard for me to debug this problem because of the
random behavior and especially because I don't understand the purpose of some
parts of the regulatory code - for example why do you calculate the
intersection at all, and don't just set on each card whatever regdomain is in
its EEPROM? What should happen if all cards have different regdomains?

Lukas Turek


diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 422da20..52536ae 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1156,6 +1156,8 @@ static int freq_reg_info_regd(struct wiphy *wiphy,
wiphy->regd)
regd = wiphy->regd;

+ regd = cfg80211_regdomain; //HACK
+
if (!regd)
return -EINVAL;

@@ -1286,7 +1288,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
bw_flags = IEEE80211_CHAN_NO_HT40;

if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
- request_wiphy && request_wiphy == wiphy &&
+ request_wiphy && /* request_wiphy == wiphy && */ //HACK
request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
/*
* This gaurantees the driver's requested regulatory domain
@@ -1327,6 +1329,8 @@ static void handle_band(struct wiphy *wiphy, enum ieee80211_band band)
static bool ignore_reg_update(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator)
{
+ return false; //HACK
+
if (!last_request)
return true;
if (initiator == NL80211_REGDOM_SET_BY_CORE &&
@@ -2499,7 +2503,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)

if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {

- intersected_rd = regdom_intersect(rd, cfg80211_regdomain);
+ intersected_rd = regdom_intersect(rd, rd); //HACK
if (!intersected_rd)
return -EINVAL;


Attachments:
(No filename) (5.21 kB)
signature.asc (836.00 B)
This is a digitally signed message part.
Download all attachments