* [PATCH 8/8] hostap: do not disable radar channels
From: Bernhard Schmidt @ 2011-01-17 13:27 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
---
src/ap/hw_features.c | 13 -------------
1 files changed, 0 insertions(+), 13 deletions(-)
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index a7f4eda..81caf63 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -126,19 +126,6 @@ int hostapd_get_hw_features(struct hostapd_iface *iface)
/* set flag for channels we can use in current regulatory
* domain */
for (j = 0; j < feature->num_channels; j++) {
- /*
- * Disable all channels that are marked not to allow
- * IBSS operation or active scanning. In addition,
- * disable all channels that require radar detection,
- * since that (in addition to full DFS) is not yet
- * supported.
- */
- if (feature->channels[j].flag &
- (HOSTAPD_CHAN_NO_IBSS |
- HOSTAPD_CHAN_PASSIVE_SCAN |
- HOSTAPD_CHAN_RADAR))
- feature->channels[j].flag |=
- HOSTAPD_CHAN_DISABLED;
if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED)
continue;
wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
--
1.5.6.5
^ permalink raw reply related
* [PATCH 7/8] hostap: handle interference on current channel
From: Bernhard Schmidt @ 2011-01-17 13:26 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
---
src/ap/hostapd.c | 32 ++++++++++++++++++++++++++++++++
1 files changed, 32 insertions(+), 0 deletions(-)
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index a065fc9..1024d73 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -993,6 +993,34 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
}
+static void hostapd_radar_flags_cb(struct hostapd_data *hapd)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ u32 flags;
+
+ iface->radar_cac_cb = NULL;
+ iface->radar_flags_cb = NULL;
+ flags = hostapd_hw_get_radar_flags(hapd, iface->conf->channel);
+ if ((flags & HOSTAPD_CHAN_RADAR_CLEAR)) {
+ hostapd_reload_bss(hapd);
+ } else if ((flags & HOSTAPD_CHAN_RADAR_INTERFERENCE)) {
+ int chan = iface->conf->channel;
+ u32 newflags;
+ iface->conf->channel = 0;
+ if (hostapd_select_random_channel(iface))
+ iface->conf->channel = chan;
+ newflags = hostapd_hw_get_radar_flags(hapd,
+ iface->conf->channel);
+ if ((newflags & HOSTAPD_CHAN_RADAR_INTERFERENCE))
+ iface->radar_flags_cb = hostapd_radar_flags_cb;
+ else
+ hostapd_radar_flags_cb(hapd);
+ } else {
+ hostapd_channel_availability_check(hapd);
+ iface->radar_cac_cb = hostapd_radar_flags_cb;
+ }
+}
+
void hostapd_radar_flags_changed(struct hostapd_data *hapd, int freq, u32 flags)
{
struct hostapd_iface *iface = hapd->iface;
@@ -1003,4 +1031,8 @@ void hostapd_radar_flags_changed(struct hostapd_data *hapd, int freq, u32 flags)
iface->radar_flags_cb(hapd);
return;
}
+ if (iface->radar_cac_cb || iface->freq != freq)
+ return;
+ else if ((flags & HOSTAPD_CHAN_RADAR_INTERFERENCE))
+ hostapd_radar_flags_cb(hapd);
}
--
1.5.6.5
^ permalink raw reply related
* [PATCH 5/5] cfg80211: userspace commands/notifications
From: Bernhard Schmidt @ 2011-01-17 11:49 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
---
include/linux/nl80211.h | 11 +++++
include/net/cfg80211.h | 18 ++++++++
net/mac80211/cfg.c | 1 +
net/mac80211/radar.c | 21 +++++++++
net/wireless/nl80211.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.h | 4 ++
net/wireless/util.c | 20 +++++++++
7 files changed, 179 insertions(+), 0 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index acb3c33..fa65287 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -410,6 +410,12 @@
* notification. This event is used to indicate that an unprotected
* disassociation frame was dropped when MFP is in use.
*
+ * @NL80211_CMD_RADAR_CAC_START: Request a CAC
+ * @NL80211_CMD_RADAR_CAC_STOP: Stop as CAC earler
+ * @NL80211_CMD_RADAR_CAC_DONE: Notification sent if a CAC has completed.
+ * @NL80211_CMD_RADAR_FLAGS_CHANGED: Notification sent if channel flags
+ * have changed.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -522,6 +528,11 @@ enum nl80211_commands {
NL80211_CMD_UNPROT_DEAUTHENTICATE,
NL80211_CMD_UNPROT_DISASSOCIATE,
+ NL80211_CMD_RADAR_CAC_START,
+ NL80211_CMD_RADAR_CAC_STOP,
+ NL80211_CMD_RADAR_CAC_DONE,
+ NL80211_CMD_RADAR_FLAGS_CHANGED,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1e9a052..4f77662 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1200,6 +1200,8 @@ struct cfg80211_pmksa {
* (also see nl80211.h @NL80211_ATTR_WIPHY_ANTENNA_TX).
*
* @get_antenna: Get current antenna configuration from device (tx_ant, rx_ant).
+ *
+ * @radar_cac: Request CAC.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy);
@@ -1367,6 +1369,8 @@ struct cfg80211_ops {
int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
+
+ int (*radar_cac)(struct wiphy *wiphy, int enable);
};
/*
@@ -2720,6 +2724,20 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
void cfg80211_cqm_pktloss_notify(struct net_device *dev,
const u8 *peer, u32 num_packets, gfp_t gfp);
+/**
+ * cfg80211_radar_cac_done - notify userspace that a CAC has been done.
+ * @wiphy: the wireless device to give the hint
+ */
+int cfg80211_radar_cac_done(struct wiphy *wiphy);
+
+/**
+ * cfg80211_radar_flags_changed - notify userspace about channel flag changes
+ * @wiphy: the wireless device to give the hint
+ * @channel: the channel on which flag changes occurred
+ */
+int cfg80211_radar_flags_changed(struct wiphy *wiphy,
+ struct ieee80211_channel *channel);
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a6a2c0b..43f657d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1999,4 +1999,5 @@ struct cfg80211_ops mac80211_config_ops = {
.mgmt_frame_register = ieee80211_mgmt_frame_register,
.set_antenna = ieee80211_set_antenna,
.get_antenna = ieee80211_get_antenna,
+ .radar_cac = ieee80211_radar_cac,
};
diff --git a/net/mac80211/radar.c b/net/mac80211/radar.c
index afb2ae1..d825e3c 100644
--- a/net/mac80211/radar.c
+++ b/net/mac80211/radar.c
@@ -18,8 +18,10 @@
static void cac_timer(unsigned long data)
{
struct ieee80211_local *local = (void *) data;
+ struct wiphy *wiphy = local->hw.wiphy;
struct ieee80211_radar *radar = &local->radar;
struct ieee80211_channel *chan;
+ int changed = 0;
printk(KERN_INFO "CAC done\n");
@@ -27,9 +29,16 @@ static void cac_timer(unsigned long data)
mutex_lock(&radar->mtx);
if ((chan->flags & IEEE80211_CHAN_RADAR_INTERFERENCE) == 0) {
chan->flags |= IEEE80211_CHAN_RADAR_CLEAR;
+ changed = 1;
}
+ mutex_unlock(&radar->mtx);
+ if (changed)
+ cfg80211_radar_flags_changed(wiphy, chan);
+
+ mutex_lock(&radar->mtx);
radar->cac = 0;
mutex_unlock(&radar->mtx);
+ cfg80211_radar_cac_done(wiphy);
}
int ieee80211_radar_cac(struct wiphy *wiphy, int enable)
@@ -52,9 +61,12 @@ int ieee80211_radar_cac(struct wiphy *wiphy, int enable)
mutex_lock(&radar->mtx);
radar->cac = 0;
mutex_unlock(&radar->mtx);
+ cfg80211_radar_cac_done(wiphy);
return 0;
}
if (enable) {
+ int changed = 0;
+
if ((chan->flags & IEEE80211_CHAN_RADAR_INTERFERENCE))
return -EINVAL;
@@ -65,7 +77,12 @@ int ieee80211_radar_cac(struct wiphy *wiphy, int enable)
if ((chan->flags & IEEE80211_CHAN_RADAR) &&
(chan->flags & IEEE80211_CHAN_RADAR_CLEAR)) {
chan->flags &= ~IEEE80211_CHAN_RADAR_CLEAR;
+ changed = 1;
}
+ mutex_unlock(&radar->mtx);
+ if (changed)
+ cfg80211_radar_flags_changed(wiphy, chan);
+ mutex_lock(&radar->mtx);
radar->cac = 1;
mutex_unlock(&radar->mtx);
mod_timer(&radar->cac_timer, jiffies +
@@ -78,6 +95,7 @@ int ieee80211_radar_cac(struct wiphy *wiphy, int enable)
static void nol_timer(unsigned long data)
{
struct ieee80211_local *local = (void *) data;
+ struct wiphy *wiphy = local->hw.wiphy;
struct ieee80211_radar *radar = &local->radar;
struct ieee80211_radar_nol_list *nol, *tmp;
@@ -93,6 +111,7 @@ static void nol_timer(unsigned long data)
list_del(&nol->list);
mutex_unlock(&radar->mtx);
kfree(nol);
+ cfg80211_radar_flags_changed(wiphy, chan);
}
}
@@ -103,6 +122,7 @@ int ieee80211_radar_interference(struct ieee80211_hw *hw,
struct ieee80211_channel *chan)
{
struct ieee80211_local *local = hw_to_local(hw);
+ struct wiphy *wiphy = local->hw.wiphy;
struct ieee80211_radar *radar = &local->radar;
struct ieee80211_radar_nol_list *nol, *tmp;
@@ -131,6 +151,7 @@ int ieee80211_radar_interference(struct ieee80211_hw *hw,
chan->flags |= IEEE80211_CHAN_RADAR_INTERFERENCE;
list_add_tail(&nol->list, &radar->nol_list);
mutex_unlock(&radar->mtx);
+ cfg80211_radar_flags_changed(wiphy, chan);
return 0;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0524423..2f43b6e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4729,6 +4729,26 @@ out:
return err;
}
+static int nl80211_radar_start_cac(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+
+ if (!rdev->ops->radar_cac)
+ return -EOPNOTSUPP;
+
+ return rdev->ops->radar_cac(&rdev->wiphy, 1);
+}
+
+static int nl80211_radar_stop_cac(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+
+ if (!rdev->ops->radar_cac)
+ return -EOPNOTSUPP;
+
+ return rdev->ops->radar_cac(&rdev->wiphy, 0);
+}
+
static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -5271,6 +5291,22 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_RADAR_CAC_START,
+ .doit = nl80211_radar_start_cac,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ NL80211_FLAG_NEED_RTNL,
+ },
+ {
+ .cmd = NL80211_CMD_RADAR_CAC_STOP,
+ .doit = nl80211_radar_stop_cac,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ NL80211_FLAG_NEED_RTNL,
+ },
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -6128,6 +6164,74 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
nlmsg_free(msg);
}
+void nl80211_radar_cac_done(struct cfg80211_registered_device *rdev)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_CAC_DONE);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, GFP_KERNEL);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+}
+
+void nl80211_radar_flags_changed(struct cfg80211_registered_device *rdev,
+ struct ieee80211_channel *chan)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_FLAGS_CHANGED);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_FREQ, chan->center_freq);
+ if ((chan->flags & IEEE80211_CHAN_RADAR_CLEAR))
+ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR_CLEAR);
+ if ((chan->flags & IEEE80211_CHAN_RADAR_INTERFERENCE))
+ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR_INTERFERENCE);
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, GFP_KERNEL);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+}
+
static int nl80211_netlink_notify(struct notifier_block * nb,
unsigned long state,
void *_notify)
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index e3f7fa8..e7f84d8 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -98,4 +98,8 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *peer,
u32 num_packets, gfp_t gfp);
+void nl80211_radar_cac_done(struct cfg80211_registered_device *rdev);
+void nl80211_radar_flags_changed(struct cfg80211_registered_device *rdev,
+ struct ieee80211_channel *chan);
+
#endif /* __NET_WIRELESS_NL80211_H */
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 7620ae2..3c87c2f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -9,6 +9,7 @@
#include <net/cfg80211.h>
#include <net/ip.h>
#include "core.h"
+#include "nl80211.h"
struct ieee80211_rate *
ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
@@ -885,3 +886,22 @@ u16 cfg80211_calculate_bitrate(struct rate_info *rate)
/* do NOT round down here */
return (bitrate + 50000) / 100000;
}
+
+int cfg80211_radar_cac_done(struct wiphy *wiphy)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ nl80211_radar_cac_done(rdev);
+ return 0;
+}
+EXPORT_SYMBOL(cfg80211_radar_cac_done);
+
+int cfg80211_radar_flags_changed(struct wiphy *wiphy,
+ struct ieee80211_channel *chan)
+{
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ nl80211_radar_flags_changed(rdev, chan);
+ return 0;
+}
+EXPORT_SYMBOL(cfg80211_radar_flags_changed);
--
1.5.6.5
^ permalink raw reply related
* [PATCH 2/5] mac80211: initialize radar params + add driver API
From: Bernhard Schmidt @ 2011-01-17 9:16 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
- ieee80211_radar_update_params() can be used by drivers to update regdomain
related parameters on regulatory changes.
- radar_detection is used to identify if a driver has support for radar
detection or not. It is called when switching from and to a channel
marked as radar detection required.
---
include/net/mac80211.h | 11 ++++++
net/mac80211/Makefile | 3 +-
net/mac80211/cfg.c | 5 +++
net/mac80211/driver-ops.h | 14 +++++++
net/mac80211/driver-trace.h | 21 +++++++++++
net/mac80211/ieee80211_i.h | 3 ++
net/mac80211/main.c | 5 +++
net/mac80211/radar.c | 84 +++++++++++++++++++++++++++++++++++++++++++
net/mac80211/radar.h | 36 ++++++++++++++++++
9 files changed, 181 insertions(+), 1 deletions(-)
create mode 100644 net/mac80211/radar.c
create mode 100644 net/mac80211/radar.h
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 62c0ce2..b158be5 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1767,6 +1767,8 @@ enum ieee80211_ampdu_mlme_action {
* ieee80211_remain_on_channel_expired(). This callback may sleep.
* @cancel_remain_on_channel: Requests that an ongoing off-channel period is
* aborted before it expires. This callback may sleep.
+ *
+ * @radar_detection: Enable or disable radar detection on current channel.
*/
struct ieee80211_ops {
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1845,6 +1847,8 @@ struct ieee80211_ops {
enum nl80211_channel_type channel_type,
int duration);
int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
+
+ int (*radar_detection)(struct ieee80211_hw *hw, int enable);
};
/**
@@ -2762,6 +2766,13 @@ void ieee80211_ready_on_channel(struct ieee80211_hw *hw);
*/
void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw);
+/**
+ * ieee80211_radar_update_params - update regdomain related radar parameteters
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ */
+void ieee80211_radar_update_params(struct ieee80211_hw *hw,
+ const struct ieee80211_regdomain *regd);
+
/* Rate control API */
/**
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index fdb54e6..deff05b 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -24,7 +24,8 @@ mac80211-y := \
util.o \
wme.o \
event.o \
- chan.o
+ chan.o \
+ radar.o
mac80211-$(CONFIG_MAC80211_LEDS) += led.o
mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4bc8a92..a6a2c0b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -18,6 +18,7 @@
#include "cfg.h"
#include "rate.h"
#include "mesh.h"
+#include "radar.h"
static struct net_device *ieee80211_add_iface(struct wiphy *wiphy, char *name,
enum nl80211_iftype type,
@@ -1232,6 +1233,8 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
break;
}
+ ieee80211_radar_detection_disable(local, local->oper_channel);
+
local->oper_channel = chan;
if (!ieee80211_set_channel_type(local, sdata, channel_type))
@@ -1241,6 +1244,8 @@ static int ieee80211_set_channel(struct wiphy *wiphy,
if (sdata && sdata->vif.type != NL80211_IFTYPE_MONITOR)
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
+ ieee80211_radar_detection_enable(local, chan);
+
return 0;
}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 98d5899..b8bcf46 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -495,4 +495,18 @@ static inline int drv_cancel_remain_on_channel(struct ieee80211_local *local)
return ret;
}
+static inline int drv_radar_detection(struct ieee80211_local *local, int enable)
+{
+ int ret = -EOPNOTSUPP;
+
+ might_sleep();
+
+ trace_drv_radar_detection(local, enable);
+ if (local->ops->radar_detection)
+ ret = local->ops->radar_detection(&local->hw, enable);
+ trace_drv_return_int(local, ret);
+
+ return ret;
+}
+
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 49c8421..09cd205 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -1250,6 +1250,27 @@ TRACE_EVENT(api_remain_on_channel_expired,
)
);
+TRACE_EVENT(drv_radar_detection,
+ TP_PROTO(struct ieee80211_local *local, int enable),
+
+ TP_ARGS(local, enable),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(int, enable)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->enable = enable;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " enable:%d",
+ LOCAL_PR_ARG, __entry->enable
+ )
+);
+
/*
* Tracing for internal functions
* (which may also be called in response to driver calls)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index c47d7c0..5c46b14 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -29,6 +29,7 @@
#include <net/mac80211.h>
#include "key.h"
#include "sta_info.h"
+#include "radar.h"
struct ieee80211_local;
@@ -929,6 +930,8 @@ struct ieee80211_local {
struct notifier_block network_latency_notifier;
struct notifier_block ifa_notifier;
+ struct ieee80211_radar radar;
+
/*
* The dynamic ps timeout configured from user space via WEXT -
* this will override whatever chosen by mac80211 internally.
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index a46ff06..5841920 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -32,6 +32,7 @@
#include "led.h"
#include "cfg.h"
#include "debugfs.h"
+#include "radar.h"
bool ieee80211_disable_40mhz_24ghz;
@@ -621,6 +622,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
ieee80211_hw_roc_setup(local);
+ ieee80211_radar_init(local);
+
return local_to_hw(local);
}
EXPORT_SYMBOL(ieee80211_alloc_hw);
@@ -891,6 +894,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
+ ieee80211_radar_deinit(local);
+
tasklet_kill(&local->tx_pending_tasklet);
tasklet_kill(&local->tasklet);
diff --git a/net/mac80211/radar.c b/net/mac80211/radar.c
new file mode 100644
index 0000000..9f41dd7
--- /dev/null
+++ b/net/mac80211/radar.c
@@ -0,0 +1,84 @@
+/*
+ * Radar handling
+ *
+ * Copyright 2011 Bernhard Schmidt <bernhard.schmidt@saxnet.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <net/mac80211.h>
+#include <net/rtnetlink.h>
+
+#include "ieee80211_i.h"
+#include "driver-ops.h"
+#include "radar.h"
+
+int ieee80211_radar_detection_enable(struct ieee80211_local *local,
+ struct ieee80211_channel *chan)
+{
+ int ret = 0;
+
+ if ((chan->flags & IEEE80211_CHAN_RADAR))
+ ret = drv_radar_detection(local, 1);
+
+ return ret;
+}
+
+int ieee80211_radar_detection_disable(struct ieee80211_local *local,
+ struct ieee80211_channel *chan)
+{
+ int ret = 0;
+
+ if ((chan->flags & IEEE80211_CHAN_RADAR))
+ ret = drv_radar_detection(local, 0);
+
+ return ret;
+}
+
+static struct ieee80211_radar_parameters regdomain_params[] = {
+ { .cac_period = 60, .nol_period = 1800 }, /* FCC, correct? */
+ { .cac_period = 60, .nol_period = 1800 }, /* ETSI */
+ { .cac_period = 60, .nol_period = 1800 }, /* JP, correct? */
+};
+
+void ieee80211_radar_update_params(struct ieee80211_hw *hw,
+ const struct ieee80211_regdomain *regd)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_radar *radar = &local->radar;
+
+ switch (regd->flags & NL80211_CFLAG_ALL_DFS_FLAGS) {
+ case NL80211_CFLAG_DFS_ETSI:
+ radar->params = ®domain_params[1];
+ break;
+ case NL80211_CFLAG_DFS_JP:
+ radar->params = ®domain_params[2];
+ break;
+ default:
+ radar->params = ®domain_params[0];
+ break;
+ }
+}
+EXPORT_SYMBOL(ieee80211_radar_update_params);
+
+void ieee80211_radar_init(struct ieee80211_local *local)
+{
+ struct ieee80211_radar *radar = &local->radar;
+
+ /*
+ * NB: use FCC by default, will be updated later once regulatory
+ * information are available.
+ */
+ radar->params = ®domain_params[0];
+
+ mutex_init(&radar->mtx);
+}
+
+void ieee80211_radar_deinit(struct ieee80211_local *local)
+{
+ struct ieee80211_radar *radar = &local->radar;
+
+ mutex_destroy(&radar->mtx);
+}
diff --git a/net/mac80211/radar.h b/net/mac80211/radar.h
new file mode 100644
index 0000000..6536e28
--- /dev/null
+++ b/net/mac80211/radar.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2011 Bernhard Schmidt <bernhard.schmidt@saxnet.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef RADAR_H
+#define RADAR_H
+
+/*
+ * Regdomain related parameters.
+ */
+struct ieee80211_radar_parameters {
+
+ /* Time in seconds for a CAC period. */
+ int cac_period;
+
+ /* Time in seconds a channel is on the no operations list. */
+ int nol_period;
+};
+
+struct ieee80211_radar {
+ struct mutex mtx;
+ struct ieee80211_radar_parameters *params;
+};
+
+int ieee80211_radar_detection_enable(struct ieee80211_local *local,
+ struct ieee80211_channel *chan);
+int ieee80211_radar_detection_disable(struct ieee80211_local *local,
+ struct ieee80211_channel *chan);
+void ieee80211_radar_init(struct ieee80211_local *local);
+void ieee80211_radar_deinit(struct ieee80211_local *local);
+
+#endif
--
1.5.6.5
^ permalink raw reply related
* [PATCH 4/8] hostap: sync nl80211_copy.h
From: Bernhard Schmidt @ 2011-01-17 13:07 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
---
src/drivers/nl80211_copy.h | 17 +++++++++++++++++
1 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 7483a89..960341c 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -406,6 +406,12 @@
* notification. This event is used to indicate that an unprotected
* disassociation frame was dropped when MFP is in use.
*
+ * @NL80211_CMD_RADAR_CAC_START: Request a CAC
+ * @NL80211_CMD_RADAR_CAC_STOP: Stop as CAC earler
+ * @NL80211_CMD_RADAR_CAC_DONE: Notification sent if a CAC has completed.
+ * @NL80211_CMD_RADAR_FLAGS_CHANGED: Notification sent if channel flags
+ * have changed.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -518,6 +524,11 @@ enum nl80211_commands {
NL80211_CMD_UNPROT_DEAUTHENTICATE,
NL80211_CMD_UNPROT_DISASSOCIATE,
+ NL80211_CMD_RADAR_CAC_START,
+ NL80211_CMD_RADAR_CAC_STOP,
+ NL80211_CMD_RADAR_CAC_DONE,
+ NL80211_CMD_RADAR_FLAGS_CHANGED,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1338,6 +1349,10 @@ enum nl80211_band_attr {
* (100 * dBm).
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
* currently defined
+ * @NL80211_FREQUENCY_ATTR_RADAR_CLEAR: during a full CAC no interference has
+ * been detected
+ * @NL80211_FREQUENCY_ATTR_RADAR_INTERFERENCE: either during a CAC or
+ * in-service monitoring radar interference was detected
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
*/
enum nl80211_frequency_attr {
@@ -1348,6 +1363,8 @@ enum nl80211_frequency_attr {
NL80211_FREQUENCY_ATTR_NO_IBSS,
NL80211_FREQUENCY_ATTR_RADAR,
NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
+ NL80211_FREQUENCY_ATTR_RADAR_CLEAR,
+ NL80211_FREQUENCY_ATTR_RADAR_INTEFERENCE,
/* keep last */
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
--
1.5.6.5
^ permalink raw reply related
* [PATCH 3/8] hostapd: select random channel of the list
From: Bernhard Schmidt @ 2011-01-17 13:00 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
---
src/ap/hw_features.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/ap/hw_features.h | 1 +
2 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 133ed74..743d567 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -27,6 +27,58 @@
#include "hw_features.h"
+int hostapd_select_random_channel(struct hostapd_iface *iface)
+{
+ int i, j, ret;
+
+ if (iface->conf->channel_list == NULL ||
+ iface->conf->channel_list[0] == -1)
+ return -1;
+
+ ret = -1;
+ if (iface->conf->channel == 0 && iface->conf->channel_list != NULL) {
+ int *chans, chans_num = 1, hw_chans_num;
+ u8 buf;
+
+ for (i = 0; iface->conf->channel_list[i] > 0; i++)
+ chans_num++;
+
+ chans = os_malloc(sizeof(int) * chans_num);
+ if (chans == NULL)
+ return -1;
+ os_memcpy(chans, iface->conf->channel_list,
+ sizeof(int) * chans_num);
+
+ hw_chans_num = iface->current_mode->num_channels;
+ buf = chans_num;
+ do {
+ struct hostapd_channel_data *hchan = NULL;
+
+ for (i = j = 0; i < chans_num; i++, j++) {
+ if (i == buf)
+ j++;
+ chans[i] = chans[j];
+ }
+
+ os_get_random(&buf, 1);
+ buf %= chans_num;
+
+ for (i = 0; i < hw_chans_num; i++) {
+ hchan = &iface->current_mode->channels[i];
+ if (hchan->chan == chans[buf] &&
+ !(hchan->flag & HOSTAPD_CHAN_DISABLED)) {
+ iface->conf->channel = hchan->chan;
+ ret = 0;
+ break;
+ }
+ }
+ chans_num--;
+ } while (iface->conf->channel == 0 && chans_num > 0);
+ os_free(chans);
+ }
+ return ret;
+}
+
void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
size_t num_hw_features)
{
@@ -642,6 +694,8 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface)
break;
}
}
+ if (iface->conf->channel == 0 && !hostapd_select_random_channel(iface))
+ ok = 1;
if (ok && iface->conf->secondary_channel) {
int sec_ok = 0;
int sec_chan = iface->conf->channel +
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index 88c2322..f800562 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -17,6 +17,7 @@
#define HW_FEATURES_H
#ifdef NEED_AP_MLME
+int hostapd_select_random_channel(struct hostapd_iface *iface);
void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
size_t num_hw_features);
int hostapd_get_hw_features(struct hostapd_iface *iface);
--
1.5.6.5
^ permalink raw reply related
* [PATCH 4/5] mac80211: add primarily CAC support
From: Bernhard Schmidt @ 2011-01-17 10:24 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
---
net/mac80211/radar.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/radar.h | 4 +++
2 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/net/mac80211/radar.c b/net/mac80211/radar.c
index e90b8bf..afb2ae1 100644
--- a/net/mac80211/radar.c
+++ b/net/mac80211/radar.c
@@ -15,6 +15,66 @@
#include "driver-ops.h"
#include "radar.h"
+static void cac_timer(unsigned long data)
+{
+ struct ieee80211_local *local = (void *) data;
+ struct ieee80211_radar *radar = &local->radar;
+ struct ieee80211_channel *chan;
+
+ printk(KERN_INFO "CAC done\n");
+
+ chan = local->oper_channel;
+ mutex_lock(&radar->mtx);
+ if ((chan->flags & IEEE80211_CHAN_RADAR_INTERFERENCE) == 0) {
+ chan->flags |= IEEE80211_CHAN_RADAR_CLEAR;
+ }
+ radar->cac = 0;
+ mutex_unlock(&radar->mtx);
+}
+
+int ieee80211_radar_cac(struct wiphy *wiphy, int enable)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_radar *radar = &local->radar;
+ struct ieee80211_channel *chan = local->oper_channel;
+ int ret;
+
+ ret = ieee80211_radar_detection_enable(local, chan);
+ if (ret != 0)
+ return ret;
+
+ if (!enable && !radar->cac)
+ return -EINVAL;
+ if (!enable && radar->cac) {
+ printk(KERN_INFO "stopping CAC\n");
+
+ del_timer_sync(&radar->cac_timer);
+ mutex_lock(&radar->mtx);
+ radar->cac = 0;
+ mutex_unlock(&radar->mtx);
+ return 0;
+ }
+ if (enable) {
+ if ((chan->flags & IEEE80211_CHAN_RADAR_INTERFERENCE))
+ return -EINVAL;
+
+ printk(KERN_INFO "starting CAC\n");
+
+ del_timer_sync(&radar->cac_timer);
+ mutex_lock(&radar->mtx);
+ if ((chan->flags & IEEE80211_CHAN_RADAR) &&
+ (chan->flags & IEEE80211_CHAN_RADAR_CLEAR)) {
+ chan->flags &= ~IEEE80211_CHAN_RADAR_CLEAR;
+ }
+ radar->cac = 1;
+ mutex_unlock(&radar->mtx);
+ mod_timer(&radar->cac_timer, jiffies +
+ msecs_to_jiffies(radar->params->cac_period * 1000));
+ }
+
+ return 0;
+}
+
static void nol_timer(unsigned long data)
{
struct ieee80211_local *local = (void *) data;
@@ -136,6 +196,9 @@ void ieee80211_radar_init(struct ieee80211_local *local)
mutex_init(&radar->mtx);
+ radar->cac = 0;
+ setup_timer(&radar->cac_timer, cac_timer, (unsigned long)local);
+
INIT_LIST_HEAD(&radar->nol_list);
setup_timer(&radar->nol_timer, nol_timer, (unsigned long)local);
mod_timer(&radar->nol_timer, jiffies + msecs_to_jiffies(1000));
@@ -146,6 +209,8 @@ void ieee80211_radar_deinit(struct ieee80211_local *local)
struct ieee80211_radar *radar = &local->radar;
struct ieee80211_radar_nol_list *nol, *tmp;
+ del_timer_sync(&radar->cac_timer);
+
del_timer_sync(&radar->nol_timer);
mutex_lock(&radar->mtx);
list_for_each_entry_safe(nol, tmp, &radar->nol_list, list) {
diff --git a/net/mac80211/radar.h b/net/mac80211/radar.h
index 79684b5..6e8bc36 100644
--- a/net/mac80211/radar.h
+++ b/net/mac80211/radar.h
@@ -31,10 +31,14 @@ struct ieee80211_radar {
struct mutex mtx;
struct ieee80211_radar_parameters *params;
+ int cac;
+ struct timer_list cac_timer;
+
struct timer_list nol_timer;
struct list_head nol_list;
};
+int ieee80211_radar_cac(struct wiphy *wiphy, int enable);
int ieee80211_radar_detection_enable(struct ieee80211_local *local,
struct ieee80211_channel *chan);
int ieee80211_radar_detection_disable(struct ieee80211_local *local,
--
1.5.6.5
^ permalink raw reply related
* [PATCH 2/8] hostap: add channel_list config parameter
From: Bernhard Schmidt @ 2011-01-17 12:56 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
---
hostapd/config_file.c | 7 +++++++
src/ap/ap_config.c | 1 +
src/ap/ap_config.h | 1 +
3 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index f6b9926..119a4bb 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -1736,6 +1736,13 @@ struct hostapd_config * hostapd_config_read(const char *fname)
}
} else if (os_strcmp(buf, "channel") == 0) {
conf->channel = atoi(pos);
+ } else if (os_strcmp(buf, "channel_list") == 0) {
+ if (hostapd_parse_int_list(&conf->channel_list,
+ pos)) {
+ wpa_printf(MSG_ERROR, "Line %d: invalid channel"
+ " list", line);
+ errors++;
+ }
} else if (os_strcmp(buf, "beacon_int") == 0) {
int val = atoi(pos);
/* MIB defines range as 1..65535, but very small values
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 702cb76..38e70fb 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -466,6 +466,7 @@ void hostapd_config_free(struct hostapd_config *conf)
os_free(conf->bss);
os_free(conf->supported_rates);
os_free(conf->basic_rates);
+ os_free(conf->channel_list);
os_free(conf);
}
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 0a929d6..57c977d 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -340,6 +340,7 @@ struct hostapd_config {
int fragm_threshold;
u8 send_probe_response;
u8 channel;
+ int *channel_list;
enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */
enum {
LONG_PREAMBLE = 0,
--
1.5.6.5
^ permalink raw reply related
* [PATCH 1/8] hostap: make hostapd_parse_rates generic
From: Bernhard Schmidt @ 2011-01-17 12:55 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
---
hostapd/config_file.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 4938611..f6b9926 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -646,14 +646,14 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx,
}
-static int hostapd_parse_rates(int **rate_list, char *val)
+static int hostapd_parse_int_list(int **int_list, char *val)
{
int *list;
int count;
char *pos, *end;
- os_free(*rate_list);
- *rate_list = NULL;
+ os_free(*int_list);
+ *int_list = NULL;
pos = val;
count = 0;
@@ -680,7 +680,7 @@ static int hostapd_parse_rates(int **rate_list, char *val)
}
list[count] = -1;
- *rate_list = list;
+ *int_list = list;
return 0;
}
@@ -1785,13 +1785,14 @@ struct hostapd_config * hostapd_config_read(const char *fname)
} else
conf->send_probe_response = val;
} else if (os_strcmp(buf, "supported_rates") == 0) {
- if (hostapd_parse_rates(&conf->supported_rates, pos)) {
+ if (hostapd_parse_int_list(&conf->supported_rates,
+ pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid rate "
"list", line);
errors++;
}
} else if (os_strcmp(buf, "basic_rates") == 0) {
- if (hostapd_parse_rates(&conf->basic_rates, pos)) {
+ if (hostapd_parse_int_list(&conf->basic_rates, pos)) {
wpa_printf(MSG_ERROR, "Line %d: invalid rate "
"list", line);
errors++;
--
1.5.6.5
^ permalink raw reply related
* [PATCH 3/5] mac80211: add NOL functionality
From: Bernhard Schmidt @ 2011-01-17 10:05 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
NOL is a list of channels on which radar interference has been detected.
Such channels are not allowed to be used for a certain amount of time.
---
include/net/mac80211.h | 8 +++++
net/mac80211/radar.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/radar.h | 9 ++++++
3 files changed, 91 insertions(+), 0 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index b158be5..4ebc080 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2773,6 +2773,14 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw);
void ieee80211_radar_update_params(struct ieee80211_hw *hw,
const struct ieee80211_regdomain *regd);
+/**
+ * ieee80211_radar_interference - report interference on a channel
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @channel: the channel on which the event occurred
+ */
+int ieee80211_radar_interference(struct ieee80211_hw *hw,
+ struct ieee80211_channel *chan);
+
/* Rate control API */
/**
diff --git a/net/mac80211/radar.c b/net/mac80211/radar.c
index 9f41dd7..e90b8bf 100644
--- a/net/mac80211/radar.c
+++ b/net/mac80211/radar.c
@@ -15,6 +15,67 @@
#include "driver-ops.h"
#include "radar.h"
+static void nol_timer(unsigned long data)
+{
+ struct ieee80211_local *local = (void *) data;
+ struct ieee80211_radar *radar = &local->radar;
+ struct ieee80211_radar_nol_list *nol, *tmp;
+
+ list_for_each_entry_safe(nol, tmp, &radar->nol_list, list) {
+ if (time_is_before_jiffies(nol->timeout)) {
+ struct ieee80211_channel *chan = nol->chan;
+
+ printk(KERN_INFO "remove NOL chan %d\n",
+ chan->center_freq);
+
+ mutex_lock(&radar->mtx);
+ chan->flags &= ~IEEE80211_CHAN_RADAR_INTERFERENCE;
+ list_del(&nol->list);
+ mutex_unlock(&radar->mtx);
+ kfree(nol);
+ }
+ }
+
+ mod_timer(&radar->nol_timer, jiffies + msecs_to_jiffies(1000));
+}
+
+int ieee80211_radar_interference(struct ieee80211_hw *hw,
+ struct ieee80211_channel *chan)
+{
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_radar *radar = &local->radar;
+ struct ieee80211_radar_nol_list *nol, *tmp;
+
+ list_for_each_entry_safe(nol, tmp, &radar->nol_list, list) {
+ if (nol->chan == chan) {
+ mutex_lock(&radar->mtx);
+ list_del(&nol->list);
+ mutex_unlock(&radar->mtx);
+ kfree(nol);
+ break;
+ }
+ }
+
+ nol = kmalloc(sizeof(struct ieee80211_radar_nol_list), GFP_KERNEL);
+ if (nol == NULL)
+ return -ENOMEM;
+
+ nol->chan = chan;
+ nol->timeout = jiffies +
+ msecs_to_jiffies(radar->params->nol_period * 1000);
+
+ printk(KERN_INFO "add NOL chan %d\n", chan->center_freq);
+
+ mutex_lock(&radar->mtx);
+ chan->flags &= ~IEEE80211_CHAN_RADAR_CLEAR;
+ chan->flags |= IEEE80211_CHAN_RADAR_INTERFERENCE;
+ list_add_tail(&nol->list, &radar->nol_list);
+ mutex_unlock(&radar->mtx);
+
+ return 0;
+}
+EXPORT_SYMBOL(ieee80211_radar_interference);
+
int ieee80211_radar_detection_enable(struct ieee80211_local *local,
struct ieee80211_channel *chan)
{
@@ -74,11 +135,24 @@ void ieee80211_radar_init(struct ieee80211_local *local)
radar->params = ®domain_params[0];
mutex_init(&radar->mtx);
+
+ INIT_LIST_HEAD(&radar->nol_list);
+ setup_timer(&radar->nol_timer, nol_timer, (unsigned long)local);
+ mod_timer(&radar->nol_timer, jiffies + msecs_to_jiffies(1000));
}
void ieee80211_radar_deinit(struct ieee80211_local *local)
{
struct ieee80211_radar *radar = &local->radar;
+ struct ieee80211_radar_nol_list *nol, *tmp;
+
+ del_timer_sync(&radar->nol_timer);
+ mutex_lock(&radar->mtx);
+ list_for_each_entry_safe(nol, tmp, &radar->nol_list, list) {
+ list_del(&nol->list);
+ kfree(nol);
+ }
+ mutex_unlock(&radar->mtx);
mutex_destroy(&radar->mtx);
}
diff --git a/net/mac80211/radar.h b/net/mac80211/radar.h
index 6536e28..79684b5 100644
--- a/net/mac80211/radar.h
+++ b/net/mac80211/radar.h
@@ -21,9 +21,18 @@ struct ieee80211_radar_parameters {
int nol_period;
};
+struct ieee80211_radar_nol_list {
+ struct ieee80211_channel *chan;
+ unsigned long timeout;
+ struct list_head list;
+};
+
struct ieee80211_radar {
struct mutex mtx;
struct ieee80211_radar_parameters *params;
+
+ struct timer_list nol_timer;
+ struct list_head nol_list;
};
int ieee80211_radar_detection_enable(struct ieee80211_local *local,
--
1.5.6.5
^ permalink raw reply related
* [PATCH 5/8] hostap: pull in additional chan flags
From: Bernhard Schmidt @ 2011-01-17 13:14 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
---
src/ap/drv_callbacks.c | 4 +++
src/ap/hostapd.c | 5 ++++
src/ap/hostapd.h | 2 +
src/ap/hw_features.c | 44 +++++++++++++++++++++++++++++++++++++++++-
src/ap/hw_features.h | 14 +++++++++++++
src/drivers/driver.h | 22 ++++++++++++++++++++-
src/drivers/driver_nl80211.c | 31 +++++++++++++++++++++++++++++
7 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index a49248f..c55c42a 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -521,6 +521,10 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
hostapd_event_sta_low_ack(hapd, data->low_ack.addr);
break;
+ case EVENT_RADAR_FLAGS_CHANGED:
+ hostapd_radar_flags_changed(hapd, data->radar.freq,
+ data->radar.flags);
+ break;
default:
wpa_printf(MSG_DEBUG, "Unknown event %d", event);
break;
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 16d7c45..592a01f 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -916,3 +916,8 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
} else
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
}
+
+void hostapd_radar_flags_changed(struct hostapd_data *hapd, int freq, u32 flags)
+{
+ hostapd_hw_set_radar_flags(hapd, freq, flags);
+}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 0346408..e2e4234 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -235,6 +235,8 @@ void hostapd_interface_deinit(struct hostapd_iface *iface);
void hostapd_interface_free(struct hostapd_iface *iface);
void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
int reassoc);
+void hostapd_radar_flags_changed(struct hostapd_data *hapd, int freq,
+ u32 flags);
/* utils.c */
int hostapd_register_probereq_cb(struct hostapd_data *hapd,
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 743d567..04bf210 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -66,7 +66,8 @@ int hostapd_select_random_channel(struct hostapd_iface *iface)
for (i = 0; i < hw_chans_num; i++) {
hchan = &iface->current_mode->channels[i];
if (hchan->chan == chans[buf] &&
- !(hchan->flag & HOSTAPD_CHAN_DISABLED)) {
+ !(hchan->flag & HOSTAPD_CHAN_DISABLED) &&
+ !(hchan->flag & HOSTAPD_CHAN_RADAR_INTERFERENCE)) {
iface->conf->channel = hchan->chan;
ret = 0;
break;
@@ -801,3 +802,44 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
return 0;
}
+
+u32 hostapd_hw_get_radar_flags(struct hostapd_data *hapd, int chan)
+{
+ int i;
+
+ if (!hapd->iface->current_mode)
+ return 0;
+
+ for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
+ struct hostapd_channel_data *ch =
+ &hapd->iface->current_mode->channels[i];
+ if (ch->chan == chan) {
+ return (ch->flag & (HOSTAPD_CHAN_RADAR |
+ HOSTAPD_CHAN_RADAR_CLEAR |
+ HOSTAPD_CHAN_RADAR_INTERFERENCE));
+ }
+ }
+
+ return 0;
+}
+
+int hostapd_hw_set_radar_flags(struct hostapd_data *hapd, int freq, u32 flags)
+{
+ int i;
+
+ if (!hapd->iface->current_mode)
+ return 0;
+
+ for (i = 0; i < hapd->iface->current_mode->num_channels; i++) {
+ struct hostapd_channel_data *ch =
+ &hapd->iface->current_mode->channels[i];
+ if (ch->freq == freq) {
+ ch->flag &= ~(HOSTAPD_CHAN_RADAR_CLEAR |
+ HOSTAPD_CHAN_RADAR_INTERFERENCE);
+ ch->flag |= flags;
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h
index f800562..466b16b 100644
--- a/src/ap/hw_features.h
+++ b/src/ap/hw_features.h
@@ -25,6 +25,8 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface);
const char * hostapd_hw_mode_txt(int mode);
int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan);
int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq);
+u32 hostapd_hw_get_radar_flags(struct hostapd_data *hapd, int chan);
+int hostapd_hw_set_radar_flags(struct hostapd_data *hapd, int freq, u32 flags);
int hostapd_check_ht_capab(struct hostapd_iface *iface);
int hostapd_prepare_rates(struct hostapd_data *hapd,
struct hostapd_hw_modes *mode);
@@ -55,6 +57,18 @@ static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
return -1;
}
+static inline u32 hostapd_hw_get_radar_flags(struct hostapd_data *hapd,
+ int chan)
+{
+ return 0;
+}
+
+static inline int hostapd_hw_set_radar_flags(struct hostapd_data *hapd,
+ int freq, u32 flags)
+{
+ return 0;
+}
+
static inline int hostapd_check_ht_capab(struct hostapd_iface *iface)
{
return 0;
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index b8684fa..777f854 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -34,6 +34,8 @@
#define HOSTAPD_CHAN_HT40PLUS 0x00000010
#define HOSTAPD_CHAN_HT40MINUS 0x00000020
#define HOSTAPD_CHAN_HT40 0x00000040
+#define HOSTAPD_CHAN_RADAR_CLEAR 0x00000080
+#define HOSTAPD_CHAN_RADAR_INTERFERENCE 0x00000100
/**
* struct hostapd_channel_data - Channel information
@@ -2577,7 +2579,9 @@ enum wpa_event_type {
EVENT_P2P_PROV_DISC_REQUEST,
EVENT_P2P_PROV_DISC_RESPONSE,
EVENT_P2P_SD_REQUEST,
- EVENT_P2P_SD_RESPONSE
+ EVENT_P2P_SD_RESPONSE,
+
+ EVENT_RADAR_FLAGS_CHANGED,
};
@@ -3091,6 +3095,22 @@ union wpa_event_data {
const u8 *tlvs;
size_t tlvs_len;
} p2p_sd_resp;
+
+ /**
+ * struct radar_flags - Data for radar related flag changes
+ */
+ struct radar_flags {
+ /**
+ * freq - Frequency (in MHz) of the channel which needs a
+ * flag update.
+ */
+ int freq;
+
+ /**
+ * flags - New HOSTAPD_CHAN_RADAR_* flags
+ */
+ u32 flags;
+ } radar;
};
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index acb8f33..d919a73 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -1288,6 +1288,26 @@ static void nl80211_new_station_event(struct wpa_driver_nl80211_data *drv,
wpa_supplicant_event(drv->ctx, EVENT_IBSS_RSN_START, &data);
}
+static void nl80211_radar_event(struct wpa_driver_nl80211_data *drv, u32 cmd,
+ struct nlattr **tb)
+{
+ union wpa_event_data data;
+
+ switch (cmd) {
+ case NL80211_CMD_RADAR_FLAGS_CHANGED:
+ if (!tb[NL80211_FREQUENCY_ATTR_FREQ])
+ return;
+ data.radar.flags = 0;
+ data.radar.freq = nla_get_u32(tb[NL80211_FREQUENCY_ATTR_FREQ]);
+ if (tb[NL80211_FREQUENCY_ATTR_RADAR_CLEAR])
+ data.radar.flags |= HOSTAPD_CHAN_RADAR_CLEAR;
+ if (tb[NL80211_FREQUENCY_ATTR_RADAR_INTEFERENCE])
+ data.radar.flags |= HOSTAPD_CHAN_RADAR_INTERFERENCE;
+ wpa_supplicant_event(drv->ctx, EVENT_RADAR_FLAGS_CHANGED,
+ &data);
+ break;
+ }
+}
static int process_event(struct nl_msg *msg, void *arg)
{
@@ -1404,6 +1424,9 @@ static int process_event(struct nl_msg *msg, void *arg)
case NL80211_CMD_NEW_STATION:
nl80211_new_station_event(drv, tb);
break;
+ case NL80211_CMD_RADAR_FLAGS_CHANGED:
+ nl80211_radar_event(drv, gnlh->cmd, tb);
+ break;
default:
wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event "
"(cmd=%d)", gnlh->cmd);
@@ -3059,6 +3082,8 @@ static int phy_info_handler(struct nl_msg *msg, void *arg)
[NL80211_FREQUENCY_ATTR_NO_IBSS] = { .type = NLA_FLAG },
[NL80211_FREQUENCY_ATTR_RADAR] = { .type = NLA_FLAG },
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] = { .type = NLA_U32 },
+ [NL80211_FREQUENCY_ATTR_RADAR_CLEAR] = { .type = NLA_FLAG },
+ [NL80211_FREQUENCY_ATTR_RADAR_INTEFERENCE] = { .type = NLA_FLAG },
};
struct nlattr *tb_rate[NL80211_BITRATE_ATTR_MAX + 1];
@@ -3172,6 +3197,12 @@ static int phy_info_handler(struct nl_msg *msg, void *arg)
if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR])
mode->channels[idx].flag |=
HOSTAPD_CHAN_RADAR;
+ if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR_CLEAR])
+ mode->channels[idx].flag |=
+ HOSTAPD_CHAN_RADAR_CLEAR;
+ if (tb_freq[NL80211_FREQUENCY_ATTR_RADAR_INTEFERENCE])
+ mode->channels[idx].flag |=
+ HOSTAPD_CHAN_RADAR_INTERFERENCE;
if (tb_freq[NL80211_FREQUENCY_ATTR_MAX_TX_POWER] &&
!tb_freq[NL80211_FREQUENCY_ATTR_DISABLED])
--
1.5.6.5
^ permalink raw reply related
* [PATCH 1/5] mac80211: add DFS related channel flags
From: Bernhard Schmidt @ 2011-01-17 8:31 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
In-Reply-To: <201101171621.29863.bernhard.schmidt@saxnet.de>
Before a radar channel can be used, a full CAC has be done, the
IEEE80211_CHAN_RADAR_CLEAR flags indicates that this has been done. If either
during CAC or in-service monitoring interference is detected, the channel is
added to NOL and marked with IEEE80211_CHAN_RADAR_INTERFERENCE.
---
include/linux/nl80211.h | 6 ++++++
include/net/cfg80211.h | 18 ++++++++++++------
net/wireless/nl80211.c | 4 ++++
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e3c9ec7..acb3c33 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1371,6 +1371,10 @@ enum nl80211_band_attr {
* (100 * dBm).
* @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number
* currently defined
+ * @NL80211_FREQUENCY_ATTR_RADAR_CLEAR: during a full CAC no interference has
+ * been detected
+ * @NL80211_FREQUENCY_ATTR_RADAR_INTERFERENCE: either during a CAC or
+ * in-service monitoring radar interference was detected
* @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use
*/
enum nl80211_frequency_attr {
@@ -1381,6 +1385,8 @@ enum nl80211_frequency_attr {
NL80211_FREQUENCY_ATTR_NO_IBSS,
NL80211_FREQUENCY_ATTR_RADAR,
NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
+ NL80211_FREQUENCY_ATTR_RADAR_CLEAR,
+ NL80211_FREQUENCY_ATTR_RADAR_INTERFERENCE,
/* keep last */
__NL80211_FREQUENCY_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1322695..1e9a052 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -98,14 +98,20 @@ enum ieee80211_band {
* is not permitted.
* @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel
* is not permitted.
+ * @IEEE80211_CHAN_RADAR_CLEAR: during a full CAC no interference has
+ * been detected
+ * @IEEE80211_CHAN_RADAR_INTERFERENCE: either during a CAC or
+ * in-service monitoring radar interference was detected
*/
enum ieee80211_channel_flags {
- IEEE80211_CHAN_DISABLED = 1<<0,
- IEEE80211_CHAN_PASSIVE_SCAN = 1<<1,
- IEEE80211_CHAN_NO_IBSS = 1<<2,
- IEEE80211_CHAN_RADAR = 1<<3,
- IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
- IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
+ IEEE80211_CHAN_DISABLED = 1<<0,
+ IEEE80211_CHAN_PASSIVE_SCAN = 1<<1,
+ IEEE80211_CHAN_NO_IBSS = 1<<2,
+ IEEE80211_CHAN_RADAR = 1<<3,
+ IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
+ IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
+ IEEE80211_CHAN_RADAR_CLEAR = 1<<6,
+ IEEE80211_CHAN_RADAR_INTERFERENCE = 1<<7,
};
#define IEEE80211_CHAN_NO_HT40 \
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f4eb3ea..0524423 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -307,6 +307,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_NO_IBSS);
if (chan->flags & IEEE80211_CHAN_RADAR)
NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR);
+ if (chan->flags & IEEE80211_CHAN_RADAR_CLEAR)
+ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR_CLEAR);
+ if (chan->flags & IEEE80211_CHAN_RADAR_INTERFERENCE)
+ NLA_PUT_FLAG(msg, NL80211_FREQUENCY_ATTR_RADAR_INTERFERENCE);
NLA_PUT_U32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
DBM_TO_MBM(chan->max_power));
--
1.5.6.5
^ permalink raw reply related
* [RFC 0/13] DFS/radar state/userspace handling
From: Bernhard Schmidt @ 2011-01-17 15:21 UTC (permalink / raw)
To: linux-wireless; +Cc: lrodriguez, nbd, dubowoj, zefir.kurtisi, simon.wunderlich
Hi,
Based on the IRC discussions I started implementing the required bits
for handling DFS states and channel flags in cfg/mac80211 and userspace.
This is WIP, so not really complete, just wanted to get that out so we
have something to discuss about on tomorrows meeting.
Implemented so far is the complete state machine, handling CAC and NOL
as well as starting appropriate action in hostapd. Note, this is based
on top of the 'dfs region support' work posted by Luis.
TODO:
- Documentation
- CSA
- unset beacon on CAC
- unset beacon if interference is detected
- prevent beacon from being set if channel is !CLEAR
- prevent frames from being sent if channel is !CLEAR
A few bits are already there, but by far not complete, e.g. we
discard auth responses but allow probe responses and deauth frames.
--
Best regards,
Dipl.-Inf. (FH) Bernhard Schmidt (software development)
saxnet GmbH, Willy-Brandt-Ring 1, 08606 Oelsnitz
Tel. +49 (0) 3741 300 6. 100 - Fax +49 (0) 3741 300 6. 101
managing director: Steffen Dreise - county court Chemnitz - HRB 23017
http://www.saxnet.de
^ permalink raw reply
* Re: htc dream wl1251 and MSM_GPIO_TO_INT(29)
From: Bob Copeland @ 2011-01-17 15:08 UTC (permalink / raw)
To: Denis 'GNUtoo' Carikli
Cc: Kalle Valo, Grazvydas Ignotas, linux-wireless
In-Reply-To: <1295047993.24338.66.camel@gnutoo-laptop>
On Sat, Jan 15, 2011 at 12:33:13AM +0100, Denis 'GNUtoo' Carikli wrote:
> The problem is the following:
> When I do that:
> modprobe msm_wifi, wich is the old wifi activator from bob copeland
> available here:
> http://bobcopeland.com/srcs/android/msm_wifi.patch
>
> it freeze the phone, and watch -n 0.1 cat /proc/interupts trough ssh
> seem frozen too
>
> Here's the code for passing the data :
>
> static void trout_wl1251_init(void)
> {
> struct wl12xx_platform_data trout_wl1251_pdata;
> int ret;
>
> trout_wl1251_pdata.irq = MSM_GPIO_TO_INT(29);
> if (trout_wl1251_pdata.irq < 0)
> goto fail_irq;
This can't ever be true, right?
> trout_wl1251_pdata.use_eeprom = false;
> ret = wl12xx_set_platform_data(&trout_wl1251_pdata);
> if (ret < 0)
> goto fail_irq;
More often one uses "if (ret)" unless ret > 0 has special meaning.
> fail_irq:
> printk("trout wifi GPIO failed\n");
> gpio_free(TROUT_WIFI_IRQ_GPIO);
But you always free a gpio here, shouldn't there be a return in there
before the fail_irq label?
> }
>
> How should I start debugging that issue? do I need a serial cable for my
> device and kgdb(doesn't serial need IRQ?, maybe I should look how msm
> serial works)?
It could be an interrupt storm, but check the above code, and
also make sure you still have the dummy msm_wifi platform device too, and
that the msm_wifi driver is getting a struct wifi_platform_data.
Unfortunately, I don't know of an easy way to debug livelocks due to
interrupt storms other than by disabling everything and then enabling one
thing at a time until it breaks again.
It's obviously going to be a lot of work, but if you can manage to get
a current kernel booting on your hardware and dump the msm_wifi module,
that would be the ideal approach.
--
Bob Copeland %% www.bobcopeland.com
^ permalink raw reply
* Re: [PATCH] mac80211: drop non-auth 3-addr data frames when running as a 4-addr station
From: Johannes Berg @ 2011-01-17 14:20 UTC (permalink / raw)
To: Felix Fietkau; +Cc: linux-wireless, linville
In-Reply-To: <1295098708-99081-1-git-send-email-nbd@openwrt.org>
On Sat, 2011-01-15 at 14:38 +0100, Felix Fietkau wrote:
> When running as a 4-addr station against an AP that has the 4-addr VLAN
> interface and the main 3-addr AP interface bridged together, sometimes
> frames originating from the station were looping back from the 3-addr AP
> interface, causing the bridge code to emit warnings about receiving frames
> with its own source address.
> I'm not sure why this is happening yet, but I think it's a good idea to
> drop all frames (except 802.1x/EAP frames) that do not match the configured
> addressing mode, including 4-address frames sent to a 3-address station.
> User test reports indicate that the problem goes away with this patch.
>
> Signed-off-by: Felix Fietkau <nbd@openwrt.org>
> ---
> net/mac80211/rx.c | 8 ++++++--
> 1 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
> index a6701ed..54e3108 100644
> --- a/net/mac80211/rx.c
> +++ b/net/mac80211/rx.c
> @@ -1561,9 +1561,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
> sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
> return -1;
>
> + if (!ieee80211_802_1x_port_control(rx) &&
I think you need a different check there. This just checks the STA is
authorized.
johannes
^ permalink raw reply
* Re: Merging SSB and HND/AI support
From: Jonas Gorski @ 2011-01-17 14:01 UTC (permalink / raw)
To: Geert Uytterhoeven; +Cc: Michael Büsch, linux-mips, linux-wireless, netdev
In-Reply-To: <AANLkTinwGaqg8ahGWd3+_dfhrCNTQNOfO1E-EUepFJ+C@mail.gmail.com>
On 17 January 2011 14:54, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> If it's AMBA, can it be integrated with the existing code in drivers/amba/?
Hm, I once had a sentence about it there, I must have accidentally deleted it.
I tried finding similarities between Broadcom's code and ARM's AMBA
specification to better understand the code, but except some tiny ones
I couldn't find anything usable. Unfortunately I couldn't find
anything about Broadcom's AMBA implementation, except that it's "AMBA"
licensed from ARM.
Jonas
^ permalink raw reply
* Re: Merging SSB and HND/AI support
From: Geert Uytterhoeven @ 2011-01-17 13:54 UTC (permalink / raw)
To: Jonas Gorski; +Cc: Michael Büsch, linux-mips, linux-wireless, netdev
In-Reply-To: <AANLkTims0DPfG+u9qynuuj_-0WjUr1nAGLuFz3k706T-@mail.gmail.com>
On Mon, Jan 17, 2011 at 14:43, Jonas Gorski <jonas.gorski@gmail.com> wrote:
> On 17 January 2011 12:57, Michael Büsch <mb@bu3sch.de> wrote:
>> Well... I don't really like the idea of running one driver and
>> subsystem implementation on completely distinct types of silicon.
>> We will end up with the same mess that broadcom ended up with in
>> their "SB" code (broadcom's SSB backplane implementation).
>> For example, in their code the driver calls pci_enable_device() and
>> related PCI functions, even if there is no PCI device at all. The calls
>> are magically re-routed to the actual SB backplane.
>> You'd have to do the same mess with SSB. Calling ssb_device_enable()
>> will mean "enable the SSB device", if the backplane is SSB, and will
>> mean "enable the HND/AI" device, if the backplane is HND/AI.
> P.S: Any suggestions for the name? Would be "ai" okay? Technically
> it's "AMBA Interconnect", but "amba" is already taken.
If it's AMBA, can it be integrated with the existing code in drivers/amba/?
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* Re: Merging SSB and HND/AI support
From: Jonas Gorski @ 2011-01-17 13:43 UTC (permalink / raw)
To: Michael Büsch; +Cc: linux-mips, linux-wireless, netdev
In-Reply-To: <1295265468.24530.23.camel@maggie>
On 17 January 2011 12:57, Michael Büsch <mb@bu3sch.de> wrote:
> Well... I don't really like the idea of running one driver and
> subsystem implementation on completely distinct types of silicon.
> We will end up with the same mess that broadcom ended up with in
> their "SB" code (broadcom's SSB backplane implementation).
> For example, in their code the driver calls pci_enable_device() and
> related PCI functions, even if there is no PCI device at all. The calls
> are magically re-routed to the actual SB backplane.
> You'd have to do the same mess with SSB. Calling ssb_device_enable()
> will mean "enable the SSB device", if the backplane is SSB, and will
> mean "enable the HND/AI" device, if the backplane is HND/AI.
It didn't strike me as that bad, but I also didn't look at any PCI code.
> So I'm still in favor of doing a separate HND/AI bus implementation,
> even if
> that means duplicating a few lines of code.
Well, it means at least duplicating most of the chipcommon driver and
the mips core driver. But if you are fine with that, I see no problem
with having a separate driver for the AI bus.
> SSB doesn't search for SSB busses in the system, because there's no
> way to do so. The architecture (or the PCI/PCMCIA/SDIO device) registers
> the bus,
> if it detected an SSB device. So for the embedded case, it's hardcoded
> in the arch code. For the PCI case it simply depends on the PCI IDs.
> I don't see a problem here. Your arch code will already have to know
> what machine it is running on. So it will have to decide whether to
> register a SSB or HND/AI bus.
Okay. This is mostly for the embedded case, where it is possible to
create a single kernel that boots on both. The "detection" could also
be done through the cpu type (74k => register AI bus, else SSB bus)
instead of the chipid register of the common core.
>> Also I don't know
>> if it is a good idea to let arch-specific code depend on code in
>> staging.
>
> Sure. The code needs to be cleaned up and moved to the mainline kernel
> _anyway_. You don't get around this.
Yes, you are right.
So I guess the proposed course of action would be:
1. Make the HND/AI-Bus code from brcm80211 its own independent driver,
2. Re-add the non-wifi related code (chipcommon, mips, etc),
3. Clean up the code until it meets Linux' code style/quality,
4. Move it out of staging,
and finally
5. Add the required arch specific code to bcm47xx for the newer SoCs.
Jonas
P.S: Any suggestions for the name? Would be "ai" okay? Technically
it's "AMBA Interconnect", but "amba" is already taken.
^ permalink raw reply
* Re: [PATCH] wl12xx: Increase scan channel dwell time for passive scans
From: Kahn, Gery @ 2011-01-17 13:39 UTC (permalink / raw)
To: Juuso Oikarinen; +Cc: coelho, linux-wireless
In-Reply-To: <1295268140.18570.128.camel@wimaxnb.nmp.nokia.com>
Ok. Thank you
On Mon, Jan 17, 2011 at 14:42, Juuso Oikarinen
<juuso.oikarinen@nokia.com> wrote:
> On Mon, 2011-01-17 at 14:33 +0200, ext Kahn, Gery wrote:
>> Does it worth to have different value for 5GHz?
>>
>
> I guess the 100ms value benefits 2.4GHz passive scanning as well, does
> it not? In 2.4GHz band there are usually very few channels passive
> scanned (mostly channels 12 and 13 in the 00 region) so the cost of this
> increased wait time is quite little.
>
> -Juuso
>
>> On Mon, Jan 17, 2011 at 13:32, <juuso.oikarinen@nokia.com> wrote:
>> > From: Juuso Oikarinen <juuso.oikarinen@nokia.com>
>> >
>> > The passive scan channel dwell time currently used is 30ms-60ms. A typical
>> > beacon interval for AP's is 100ms. This leads to a ~30% worst-case probability
>> > of finding an AP via passive scanning.
>> >
>> > For 5GHz bands for DFS frequencies passive scanning is the only scanning
>> > option. Hence for these, the probability of finding an AP is very low.
>> >
>> > To fix this, increase the passive channel scan dwell times (also the early
>> > leave value, as 5GHz channels are still typically very silent.) Use a value
>> > of 100ms, because that covers most typical AP configurations.
>> >
>> > Based on testing the probability of finding an AP (102.4ms beacon interval) on
>> > a single scan round are as follows (based on 100 iterations):
>> >
>> > dwell min/max (ms) | probability
>> > ---------------------+------------
>> > 30/60 | 35%
>> > 60/60 | 56%
>> > 80/80 | 77%
>> > 100/100 | 100%
>> >
>> > Total scan times now and after the change:
>> >
>> > Region | Before (s) | After (s)
>> > -------+------------+----------
>> > 00 | 0.77 | 1.48
>> > FI | 0.95 | 2.01
>> > US | 0.91 | 1.76
>> >
>> > Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
>> > ---
>
>
^ permalink raw reply
* [PATCH 2.6.32.y] hostap_cs: fix sleeping function called from invalid context
From: Stanislaw Gruszka @ 2011-01-17 13:05 UTC (permalink / raw)
To: stable; +Cc: Stanislaw Gruszka, Dominik Brodowski, Tim Gardner, linux-wireless
commit 4e5518ca53be29c1ec3c00089c97bef36bfed515 upstream.
pcmcia_request_irq() and pcmcia_enable_device() are intended
to be called from process context (first function allocate memory
with GFP_KERNEL, second take a mutex). We can not take spin lock
and call them.
It's safe to move spin lock after pcmcia_enable_device() as we
still hold off IRQ until dev->base_addr is 0 and driver will
not proceed with interrupts when is not ready.
Patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=643758
Reported-and-tested-by: rbugz@biobind.com
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/hostap/hostap_cs.c | 10 ++--------
1 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index b4ff1dc..6992f8f 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -662,12 +662,6 @@ static int prism2_config(struct pcmcia_device *link)
link->dev_node = &hw_priv->node;
/*
- * Make sure the IRQ handler cannot proceed until at least
- * dev->base_addr is initialized.
- */
- spin_lock_irqsave(&local->irq_init_lock, flags);
-
- /*
* Allocate an interrupt line. Note that this does not assign a
* handler to the interrupt, unless the 'Handler' member of the
* irq structure is initialized.
@@ -690,9 +684,10 @@ static int prism2_config(struct pcmcia_device *link)
CS_CHECK(RequestConfiguration,
pcmcia_request_configuration(link, &link->conf));
+ /* IRQ handler cannot proceed until at dev->base_addr is initialized */
+ spin_lock_irqsave(&local->irq_init_lock, flags);
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
-
spin_unlock_irqrestore(&local->irq_init_lock, flags);
/* Finally, report what we've done */
@@ -724,7 +719,6 @@ static int prism2_config(struct pcmcia_device *link)
return ret;
cs_failed:
- spin_unlock_irqrestore(&local->irq_init_lock, flags);
cs_error(link, last_fn, last_ret);
failed:
--
1.7.1
^ permalink raw reply related
* [PATCH 2.6.34.y] hostap_cs: fix sleeping function called from invalid context
From: Stanislaw Gruszka @ 2011-01-17 13:04 UTC (permalink / raw)
To: stable, kernel
Cc: Kyle McMartin, Stanislaw Gruszka, Dominik Brodowski, Tim Gardner,
linux-wireless
commit 4e5518ca53be29c1ec3c00089c97bef36bfed515 upstream.
pcmcia_request_irq() and pcmcia_enable_device() are intended
to be called from process context (first function allocate memory
with GFP_KERNEL, second take a mutex). We can not take spin lock
and call them.
It's safe to move spin lock after pcmcia_enable_device() as we
still hold off IRQ until dev->base_addr is 0 and driver will
not proceed with interrupts when is not ready.
Patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=643758
Reported-and-tested-by: rbugz@biobind.com
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/hostap/hostap_cs.c | 14 +++-----------
1 files changed, 3 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index f33e18e..116b5c6 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -638,12 +638,6 @@ static int prism2_config(struct pcmcia_device *link)
link->dev_node = &hw_priv->node;
/*
- * Make sure the IRQ handler cannot proceed until at least
- * dev->base_addr is initialized.
- */
- spin_lock_irqsave(&local->irq_init_lock, flags);
-
- /*
* Allocate an interrupt line. Note that this does not assign a
* handler to the interrupt, unless the 'Handler' member of the
* irq structure is initialized.
@@ -653,7 +647,7 @@ static int prism2_config(struct pcmcia_device *link)
link->irq.Handler = prism2_interrupt;
ret = pcmcia_request_irq(link, &link->irq);
if (ret)
- goto failed_unlock;
+ goto failed;
}
/*
@@ -663,11 +657,11 @@ static int prism2_config(struct pcmcia_device *link)
*/
ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
- goto failed_unlock;
+ goto failed;
+ spin_lock_irqsave(&local->irq_init_lock, flags);
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
-
spin_unlock_irqrestore(&local->irq_init_lock, flags);
/* Finally, report what we've done */
@@ -698,8 +692,6 @@ static int prism2_config(struct pcmcia_device *link)
}
return ret;
- failed_unlock:
- spin_unlock_irqrestore(&local->irq_init_lock, flags);
failed:
kfree(hw_priv);
prism2_release((u_long)link);
--
1.7.1
^ permalink raw reply related
* [PATCH 2.6.35.y] hostap_cs: fix sleeping function called from invalid context
From: Stanislaw Gruszka @ 2011-01-17 13:03 UTC (permalink / raw)
To: stable, kernel
Cc: Kyle McMartin, Stanislaw Gruszka, Dominik Brodowski, Tim Gardner,
linux-wireless
commit 4e5518ca53be29c1ec3c00089c97bef36bfed515 upstream.
pcmcia_request_irq() and pcmcia_enable_device() are intended
to be called from process context (first function allocate memory
with GFP_KERNEL, second take a mutex). We can not take spin lock
and call them.
It's safe to move spin lock after pcmcia_enable_device() as we
still hold off IRQ until dev->base_addr is 0 and driver will
not proceed with interrupts when is not ready.
Patch resolves:
https://bugzilla.redhat.com/show_bug.cgi?id=643758
Reported-and-tested-by: rbugz@biobind.com
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
---
drivers/net/wireless/hostap/hostap_cs.c | 15 ++++++---------
1 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 29b31a6..4ebf63d 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -627,14 +627,13 @@ static int prism2_config(struct pcmcia_device *link)
hw_priv->link = link;
/*
- * Make sure the IRQ handler cannot proceed until at least
- * dev->base_addr is initialized.
+ * We enable IRQ here, but IRQ handler will not proceed
+ * until dev->base_addr is set below. This protect us from
+ * receive interrupts when driver is not initialized.
*/
- spin_lock_irqsave(&local->irq_init_lock, flags);
-
ret = pcmcia_request_irq(link, prism2_interrupt);
if (ret)
- goto failed_unlock;
+ goto failed;
/*
* This actually configures the PCMCIA socket -- setting up
@@ -643,11 +642,11 @@ static int prism2_config(struct pcmcia_device *link)
*/
ret = pcmcia_request_configuration(link, &link->conf);
if (ret)
- goto failed_unlock;
+ goto failed;
+ spin_lock_irqsave(&local->irq_init_lock, flags);
dev->irq = link->irq;
dev->base_addr = link->io.BasePort1;
-
spin_unlock_irqrestore(&local->irq_init_lock, flags);
/* Finally, report what we've done */
@@ -676,8 +675,6 @@ static int prism2_config(struct pcmcia_device *link)
return ret;
- failed_unlock:
- spin_unlock_irqrestore(&local->irq_init_lock, flags);
failed:
kfree(hw_priv);
prism2_release((u_long)link);
--
1.7.1
^ permalink raw reply related
* Re: [PATCH] wl12xx: Increase scan channel dwell time for passive scans
From: Juuso Oikarinen @ 2011-01-17 12:42 UTC (permalink / raw)
To: ext Kahn, Gery; +Cc: coelho, linux-wireless
In-Reply-To: <AANLkTikYPCqQy7ra7RHSA8fE_NR9LgoPhaKori2xhbYa@mail.gmail.com>
On Mon, 2011-01-17 at 14:33 +0200, ext Kahn, Gery wrote:
> Does it worth to have different value for 5GHz?
>
I guess the 100ms value benefits 2.4GHz passive scanning as well, does
it not? In 2.4GHz band there are usually very few channels passive
scanned (mostly channels 12 and 13 in the 00 region) so the cost of this
increased wait time is quite little.
-Juuso
> On Mon, Jan 17, 2011 at 13:32, <juuso.oikarinen@nokia.com> wrote:
> > From: Juuso Oikarinen <juuso.oikarinen@nokia.com>
> >
> > The passive scan channel dwell time currently used is 30ms-60ms. A typical
> > beacon interval for AP's is 100ms. This leads to a ~30% worst-case probability
> > of finding an AP via passive scanning.
> >
> > For 5GHz bands for DFS frequencies passive scanning is the only scanning
> > option. Hence for these, the probability of finding an AP is very low.
> >
> > To fix this, increase the passive channel scan dwell times (also the early
> > leave value, as 5GHz channels are still typically very silent.) Use a value
> > of 100ms, because that covers most typical AP configurations.
> >
> > Based on testing the probability of finding an AP (102.4ms beacon interval) on
> > a single scan round are as follows (based on 100 iterations):
> >
> > dwell min/max (ms) | probability
> > ---------------------+------------
> > 30/60 | 35%
> > 60/60 | 56%
> > 80/80 | 77%
> > 100/100 | 100%
> >
> > Total scan times now and after the change:
> >
> > Region | Before (s) | After (s)
> > -------+------------+----------
> > 00 | 0.77 | 1.48
> > FI | 0.95 | 2.01
> > US | 0.91 | 1.76
> >
> > Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
> > ---
^ permalink raw reply
* Re: [PATCH] wl12xx: Increase scan channel dwell time for passive scans
From: Kahn, Gery @ 2011-01-17 12:33 UTC (permalink / raw)
To: juuso.oikarinen; +Cc: coelho, linux-wireless
In-Reply-To: <1295263943-32110-1-git-send-email-juuso.oikarinen@nokia.com>
Does it worth to have different value for 5GHz?
On Mon, Jan 17, 2011 at 13:32, <juuso.oikarinen@nokia.com> wrote:
> From: Juuso Oikarinen <juuso.oikarinen@nokia.com>
>
> The passive scan channel dwell time currently used is 30ms-60ms. A typical
> beacon interval for AP's is 100ms. This leads to a ~30% worst-case probability
> of finding an AP via passive scanning.
>
> For 5GHz bands for DFS frequencies passive scanning is the only scanning
> option. Hence for these, the probability of finding an AP is very low.
>
> To fix this, increase the passive channel scan dwell times (also the early
> leave value, as 5GHz channels are still typically very silent.) Use a value
> of 100ms, because that covers most typical AP configurations.
>
> Based on testing the probability of finding an AP (102.4ms beacon interval) on
> a single scan round are as follows (based on 100 iterations):
>
> dwell min/max (ms) | probability
> ---------------------+------------
> 30/60 | 35%
> 60/60 | 56%
> 80/80 | 77%
> 100/100 | 100%
>
> Total scan times now and after the change:
>
> Region | Before (s) | After (s)
> -------+------------+----------
> 00 | 0.77 | 1.48
> FI | 0.95 | 2.01
> US | 0.91 | 1.76
>
> Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
> ---
> drivers/net/wireless/wl12xx/conf.h | 16 ++++++++--------
> drivers/net/wireless/wl12xx/main.c | 4 ++--
> 2 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
> index f5c048c..21b72a5 100644
> --- a/drivers/net/wireless/wl12xx/conf.h
> +++ b/drivers/net/wireless/wl12xx/conf.h
> @@ -1084,30 +1084,30 @@ struct conf_scan_settings {
> /*
> * The minimum time to wait on each channel for active scans
> *
> - * Range: 0 - 65536 tu
> + * Range: u32 tu/1000
> */
> - u16 min_dwell_time_active;
> + u32 min_dwell_time_active;
>
> /*
> * The maximum time to wait on each channel for active scans
> *
> - * Range: 0 - 65536 tu
> + * Range: u32 tu/1000
> */
> - u16 max_dwell_time_active;
> + u32 max_dwell_time_active;
>
> /*
> * The maximum time to wait on each channel for passive scans
> *
> - * Range: 0 - 65536 tu
> + * Range: u32 tu/1000
> */
> - u16 min_dwell_time_passive;
> + u32 min_dwell_time_passive;
>
> /*
> * The maximum time to wait on each channel for passive scans
> *
> - * Range: 0 - 65536 tu
> + * Range: u32 tu/1000
> */
> - u16 max_dwell_time_passive;
> + u32 max_dwell_time_passive;
>
> /*
> * Number of probe requests to transmit on each active scan channel
> diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
> index 863e660..c1814f2 100644
> --- a/drivers/net/wireless/wl12xx/main.c
> +++ b/drivers/net/wireless/wl12xx/main.c
> @@ -279,8 +279,8 @@ static struct conf_drv_settings default_conf = {
> .scan = {
> .min_dwell_time_active = 7500,
> .max_dwell_time_active = 30000,
> - .min_dwell_time_passive = 30000,
> - .max_dwell_time_passive = 60000,
> + .min_dwell_time_passive = 100000,
> + .max_dwell_time_passive = 100000,
> .num_probe_reqs = 2,
> },
> .rf = {
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: Merging SSB and HND/AI support
From: Michael Büsch @ 2011-01-17 12:00 UTC (permalink / raw)
To: Florian Fainelli; +Cc: Jonas Gorski, linux-mips, linux-wireless, netdev
In-Reply-To: <201101171220.52292.florian@openwrt.org>
On Mon, 2011-01-17 at 12:20 +0100, Florian Fainelli wrote:
> On Monday 17 January 2011 11:56:23 Michael Büsch wrote:
> > On Mon, 2011-01-17 at 11:46 +0100, Jonas Gorski wrote:
> > > Hello,
> > >
> > > I am currently looking into adding support for the newer Broadcom
> > > BCM47xx/53xx SoCs. They require having HND/AI support, which probably
> > > means merging the current SSB code and the HND/AI code from the
> > > brcm80211 driver. Is anyone already working on this?
> > >
> > > As far as I can see, there are two possibilities:
> > >
> > > a) Merge the HND/AI code into the current SSB code, or
> > >
> > > b) add the missing code for SoCs to brcm80211 and replace the SSB code
> > > with it.
> >
> > Why can't we keep those two platforms separated?
>
> That is also what I am wondering about. Considering that previous BCM47xx
> platforms use a MIPS4k core and newer one use MIPS74k or later, you would not
> be able to build a single kernel for both which takes advantages of compile-
> time optimizations targetting MIPS74k. If this ist not a big concern, then
> let's target a single kernel.
Ok, but it should be easily possible to compile both SSB and HND/AI
bus support into one kernel anyway. Nothing prevents drivers from having
an SSB and an HND/AI probe callback.
--
Greetings Michael.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox