* Re: [Driver] NEC WL300NU-G
From: u2 @ 2011-01-15 22:47 UTC (permalink / raw)
To: Gertjan van Wingerde; +Cc: linux-wireless
In-Reply-To: <4D31DBD2.9060909@gmail.com>
Gertjan,
Yes, distribution Debian I use is sometimes old...
I will wait for the 2.6.34~ appears in dist because of maintain-ability.
Thanks for your helpful reply.
Regards,
Miyagi
(2011-01-16 02:39), -------- Message --------:
> On 01/15/11 16:49, u2@whoplays.asia wrote:
>> hi,
>>
>> According to the list linuxwireless.org/en/users/Devices/USB, Wireless USB adapter NEC WL300NU-G[0x409:0x093f] is supported by ar9170usb.
>>
>> But the one I bought via www.amazon.co.jp/NEC-Aterm-WL300NU-G-PA-WL300NU-G is [0x409:0x0249] and not detected by any drivers...
>>
>> $ lsusb
>> Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
>> Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
>> Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
>> Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
>> Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
>> Bus 002 Device 006: ID 0a5c:2101 Broadcom Corp. Bluetooth Controller
>> Bus 002 Device 005: ID 0853:0100 Topre Corporation HHKB Professional
>> Bus 002 Device 004: ID 0409:005a NEC Corp. HighSpeed Hub
>> Bus 002 Device 003: ID 0409:0249 NEC Corp.
>> Bus 002 Device 002: ID 2019:ab50 PLANEX GW-US54Mini2
>> Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
>> Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
>> $ uname -a
>> Linux localhost 2.6.32-5-amd64 #1 SMP Wed Jan 12 03:40:32 UTC 2011 x86_64 GNU/Linux
>>
>> Plz anyone describe me why this one has another vendor-productID, and will this one supported?
>
> It looks like this device is supported in the latest ar9170usb driver. I can't really find in which kernel
> release support for this device has been added, but I'm almost certain that this was after 2.6.32 had been
> released (it is more likely that 2.6.34 is the first kernel release that supports your device).
>
> In other words, the kernel version that you are testing with is simply too old to support the device.
> I guess you need to upgrade to a later kernel version (or use compat-wireless).
>
> ---
> Gertjan.
>
^ permalink raw reply
* Compat-wireless release for 2011-01-15 is baked
From: Compat-wireless cronjob account @ 2011-01-15 20:04 UTC (permalink / raw)
To: linux-wireless
>From git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next
+ e70f43d...0eb1b34 akpm-end -> origin/akpm-end (forced update)
e0e736f..6ab8219 akpm-start -> origin/akpm-start
2271958..bed36d7 history -> origin/history
+ 1d506f8...e8883f8 master -> origin/master (forced update)
581548d..6ab8219 stable -> origin/stable
* [new tag] next-20110115 -> next-20110115
compat-wireless code metrics
782520 - Total upstream lines of code being pulled
2103 - backport code changes
1843 - backport code additions
260 - backport code deletions
7279 - backport from compat module
9382 - total backport code
1.1989 - % of code consists of backport work
1531 - Crap changes not yet posted
1488 - Crap additions not yet posted
43 - Crap deletions not yet posted
0.1956 - % of crap code
Base tree: linux-next.git
Base tree version: next-20110115
compat-wireless release: compat-wireless-2011-01-06-3-g8db1608-pc
^ permalink raw reply
* [PATCH v3 2/2] ath9k: Add 'misc' file to debugfs, fix queue indexes.
From: greearb @ 2011-01-15 19:13 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, Ben Greear
In-Reply-To: <1295118829-7464-1-git-send-email-greearb@candelatech.com>
From: Ben Greear <greearb@candelatech.com>
Add a misc file to show hardware op-mode, irq setup,
number of various types of VIFs and more.
Also, previous patches were using the wrong xmit queue
indexes. Change to use the internal ath9k indexes instead
of the mac80211 queue indexes.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
v3: Update to use iterator to gather vif stats. Print
calculated bssid mask as well.
This patch requires previous debugfs patches that I have posted.
:100644 100644 b0cb792... 5005621... M drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/debug.c | 128 +++++++++++++++++++++++++++++---
1 files changed, 116 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index b0cb792..5005621 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -595,10 +595,10 @@ static const struct file_operations fops_wiphy = {
do { \
len += snprintf(buf + len, size - len, \
"%s%13u%11u%10u%10u\n", str, \
- (unsigned int)(sc->tx.txq[WME_AC_BE].elem), \
- (unsigned int)(sc->tx.txq[WME_AC_BK].elem), \
- (unsigned int)(sc->tx.txq[WME_AC_VI].elem), \
- (unsigned int)(sc->tx.txq[WME_AC_VO].elem)); \
+ (unsigned int)(sc->tx.txq[ATH_TXQ_AC_BE].elem), \
+ (unsigned int)(sc->tx.txq[ATH_TXQ_AC_BK].elem), \
+ (unsigned int)(sc->tx.txq[ATH_TXQ_AC_VI].elem), \
+ (unsigned int)(sc->tx.txq[ATH_TXQ_AC_VO].elem)); \
if (len >= size) \
goto done; \
} while(0)
@@ -607,10 +607,10 @@ do { \
do { \
len += snprintf(buf + len, size - len, \
"%s%13i%11i%10i%10i\n", str, \
- list_empty(&sc->tx.txq[WME_AC_BE].elem), \
- list_empty(&sc->tx.txq[WME_AC_BK].elem), \
- list_empty(&sc->tx.txq[WME_AC_VI].elem), \
- list_empty(&sc->tx.txq[WME_AC_VO].elem)); \
+ list_empty(&sc->tx.txq[ATH_TXQ_AC_BE].elem), \
+ list_empty(&sc->tx.txq[ATH_TXQ_AC_BK].elem), \
+ list_empty(&sc->tx.txq[ATH_TXQ_AC_VI].elem), \
+ list_empty(&sc->tx.txq[ATH_TXQ_AC_VO].elem)); \
if (len >= size) \
goto done; \
} while (0)
@@ -657,10 +657,10 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
PR("hw-tx-proc-desc: ", txprocdesc);
len += snprintf(buf + len, size - len,
"%s%11p%11p%10p%10p\n", "txq-memory-address:",
- &(sc->tx.txq[WME_AC_BE]),
- &(sc->tx.txq[WME_AC_BK]),
- &(sc->tx.txq[WME_AC_VI]),
- &(sc->tx.txq[WME_AC_VO]));
+ &(sc->tx.txq[ATH_TXQ_AC_BE]),
+ &(sc->tx.txq[ATH_TXQ_AC_BK]),
+ &(sc->tx.txq[ATH_TXQ_AC_VI]),
+ &(sc->tx.txq[ATH_TXQ_AC_VO]));
if (len >= size)
goto done;
@@ -777,6 +777,99 @@ done:
return retval;
}
+static ssize_t read_file_misc(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ struct ath_hw *ah = sc->sc_ah;
+ char *buf;
+ unsigned int len = 0, size = 8000;
+ ssize_t retval = 0;
+ const char *tmp;
+ unsigned int reg;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ switch (sc->sc_ah->opmode) {
+ case NL80211_IFTYPE_ADHOC:
+ tmp = "ADHOC";
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ tmp = "MESH";
+ break;
+ case NL80211_IFTYPE_AP:
+ tmp = "AP";
+ break;
+ case NL80211_IFTYPE_STATION:
+ tmp = "STATION";
+ break;
+ default:
+ tmp = "???";
+ break;
+ }
+
+ len += snprintf(buf + len, size - len,
+ "curbssid: %pM\n"
+ "OP-Mode: %s(%i)\n"
+ "Beacon-Timer-Register: 0x%x\n",
+ common->curbssid,
+ tmp, (int)(sc->sc_ah->opmode),
+ REG_READ(ah, AR_BEACON_PERIOD));
+
+ reg = REG_READ(ah, AR_TIMER_MODE);
+ len += snprintf(buf + len, size - len, "Timer-Mode-Register: 0x%x (",
+ reg);
+ if (reg & AR_TBTT_TIMER_EN)
+ len += snprintf(buf + len, size - len, "TBTT ");
+ if (reg & AR_DBA_TIMER_EN)
+ len += snprintf(buf + len, size - len, "DBA ");
+ if (reg & AR_SWBA_TIMER_EN)
+ len += snprintf(buf + len, size - len, "SWBA ");
+ if (reg & AR_HCF_TIMER_EN)
+ len += snprintf(buf + len, size - len, "HCF ");
+ if (reg & AR_TIM_TIMER_EN)
+ len += snprintf(buf + len, size - len, "TIM ");
+ if (reg & AR_DTIM_TIMER_EN)
+ len += snprintf(buf + len, size - len, "DTIM ");
+ len += snprintf(buf + len, size - len, ")\n");
+
+ reg = sc->sc_ah->imask;
+ len += snprintf(buf + len, size - len, "imask: 0x%x (", reg);
+ if (reg & ATH9K_INT_SWBA)
+ len += snprintf(buf + len, size - len, "SWBA ");
+ if (reg & ATH9K_INT_BMISS)
+ len += snprintf(buf + len, size - len, "BMISS ");
+ if (reg & ATH9K_INT_CST)
+ len += snprintf(buf + len, size - len, "CST ");
+ if (reg & ATH9K_INT_RX)
+ len += snprintf(buf + len, size - len, "RX ");
+ if (reg & ATH9K_INT_RXHP)
+ len += snprintf(buf + len, size - len, "RXHP ");
+ if (reg & ATH9K_INT_RXLP)
+ len += snprintf(buf + len, size - len, "RXLP ");
+ if (reg & ATH9K_INT_BB_WATCHDOG)
+ len += snprintf(buf + len, size - len, "BB_WATCHDOG ");
+ /* there are other IRQs if one wanted to add them. */
+ len += snprintf(buf + len, size - len, ")\n");
+
+ len += snprintf(buf + len, size - len,
+ "VIF Counts: AP: %hi STA: %hi MESH: %hi WDS: %hi"
+ " ADHOC: %hi nvifs: %hi beacon-vifs: %hi\n",
+ sc->naps, sc->nstations, sc->nmeshes, sc->nwds,
+ sc->nadhocs, sc->nvifs, sc->nbcnvifs);
+
+ if (len > size)
+ len = size;
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts)
{
@@ -822,6 +915,13 @@ static const struct file_operations fops_stations = {
.llseek = default_llseek,
};
+static const struct file_operations fops_misc = {
+ .read = read_file_misc,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
static ssize_t read_file_recv(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1063,6 +1163,10 @@ int ath9k_init_debug(struct ath_hw *ah)
sc, &fops_stations))
goto err;
+ if (!debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy,
+ sc, &fops_misc))
+ goto err;
+
if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy,
sc, &fops_recv))
goto err;
--
1.7.2.3
^ permalink raw reply related
* [PATCH v3 1/2] ath9k: Fix up hardware mode and beacons with multiple vifs.
From: greearb @ 2011-01-15 19:13 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, Ben Greear
From: Ben Greear <greearb@candelatech.com>
When using a mixture of AP and Station interfaces,
the hardware mode was using the type of the
last VIF registered. Instead, we should keep track
of the number of different types of vifs and set the
mode accordingly.
In addtion, use the vif type instead of hardware opmode
when dealing with beacons.
Attempt to move some of the common setup code into smaller
methods so we can re-use it when changing vif mode as
well as adding/deleting vifs.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
v3: Remove vif counters and use iterator to build current
state for all interfaces as needed. Move bssid mask setting
logic to 'main.c', and combine with other summary state
setting.
:100644 100644 3108699... dab0271... M drivers/net/wireless/ath/ath9k/ath9k.h
:100644 100644 385ba03... 8de591e... M drivers/net/wireless/ath/ath9k/beacon.c
:100644 100644 0452580... e91d927... M drivers/net/wireless/ath/ath9k/main.c
:100644 100644 ea2f67c... 8def8c2... M drivers/net/wireless/ath/ath9k/recv.c
:100644 100644 2dc7095... d205c66... M drivers/net/wireless/ath/ath9k/virtual.c
drivers/net/wireless/ath/ath9k/ath9k.h | 23 ++-
drivers/net/wireless/ath/ath9k/beacon.c | 14 +-
drivers/net/wireless/ath/ath9k/main.c | 308 +++++++++++++++++++++---------
drivers/net/wireless/ath/ath9k/recv.c | 16 ++-
drivers/net/wireless/ath/ath9k/virtual.c | 48 -----
5 files changed, 263 insertions(+), 146 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 3108699..dab0271 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -568,6 +568,20 @@ struct ath_ant_comb {
struct ath_wiphy;
struct ath_rate_table;
+struct ath9k_vif_iter_data {
+ const u8 *hw_macaddr; /* phy's hardware address, set
+ * before starting iteration for
+ * valid bssid mask.
+ */
+ u8 mask[ETH_ALEN]; /* bssid mask */
+ int naps; /* number of AP vifs */
+ int nmeshes; /* number of mesh vifs */
+ int nstations; /* number of station vifs */
+ int nwds; /* number of nwd vifs */
+ int nadhocs; /* number of adhoc vifs */
+ int nothers; /* number of vifs not specified above. */
+};
+
struct ath_softc {
struct ieee80211_hw *hw;
struct device *dev;
@@ -607,10 +621,10 @@ struct ath_softc {
u32 sc_flags; /* SC_OP_* */
u16 ps_flags; /* PS_* */
u16 curtxpow;
- u8 nbcnvifs;
- u16 nvifs;
bool ps_enabled;
bool ps_idle;
+ short nbcnvifs;
+ short nvifs;
unsigned long ps_usecount;
struct ath_config config;
@@ -694,6 +708,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
+bool ath9k_uses_beacons(int type);
#ifdef CONFIG_PCI
int ath_pci_init(void);
@@ -738,5 +753,9 @@ bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
void ath_start_rfkill_poll(struct ath_softc *sc);
extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
+void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ath9k_vif_iter_data *iter_data);
+
#endif /* ATH9K_H */
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 385ba03..8de591e 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -244,9 +244,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
struct ath_buf, list);
list_del(&avp->av_bcbuf->list);
- if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
- sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC ||
- sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+ if (ath9k_uses_beacons(vif->type)) {
int slot;
/*
* Assign the vif to a beacon xmit slot. As
@@ -282,7 +280,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
/* NB: the beacon data buffer must be 32-bit aligned. */
skb = ieee80211_beacon_get(sc->hw, vif);
if (skb == NULL) {
- ath_dbg(common, ATH_DBG_BEACON, "cannot get skb\n");
+ ath_err(common, "ieee80211_beacon_get failed\n");
return -ENOMEM;
}
@@ -720,10 +718,10 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
iftype = sc->sc_ah->opmode;
}
- cur_conf->listen_interval = 1;
- cur_conf->dtim_count = 1;
- cur_conf->bmiss_timeout =
- ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
+ cur_conf->listen_interval = 1;
+ cur_conf->dtim_count = 1;
+ cur_conf->bmiss_timeout =
+ ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
/*
* It looks like mac80211 may end up using beacon interval of zero in
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 0452580..e91d927 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1366,112 +1366,251 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
}
-static int ath9k_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+bool ath9k_uses_beacons(int type)
+{
+ switch (type) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void ath9k_reclaim_beacon(struct ath_softc *sc,
+ struct ieee80211_vif *vif)
{
- struct ath_wiphy *aphy = hw->priv;
- struct ath_softc *sc = aphy->sc;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
struct ath_vif *avp = (void *)vif->drv_priv;
- enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
- int ret = 0;
- mutex_lock(&sc->mutex);
+ /* Disable SWBA interrupt */
+ sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
+ ath9k_ps_wakeup(sc);
+ ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
+ ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+ tasklet_kill(&sc->bcon_tasklet);
+ ath9k_ps_restore(sc);
+
+ ath_beacon_return(sc, avp);
+ sc->sc_flags &= ~SC_OP_BEACONS;
+
+ if (sc->nbcnvifs > 0) {
+ /* Re-enable beaconing */
+ sc->sc_ah->imask |= ATH9K_INT_SWBA;
+ ath9k_ps_wakeup(sc);
+ ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
+ ath9k_ps_restore(sc);
+ }
+}
+
+static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct ath9k_vif_iter_data *iter_data = data;
+ int i;
+
+ if (iter_data->hw_macaddr)
+ for (i = 0; i < ETH_ALEN; i++)
+ iter_data->mask[i] &=
+ ~(iter_data->hw_macaddr[i] ^ mac[i]);
switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- ic_opmode = NL80211_IFTYPE_STATION;
+ case NL80211_IFTYPE_AP:
+ iter_data->naps++;
break;
- case NL80211_IFTYPE_WDS:
- ic_opmode = NL80211_IFTYPE_WDS;
+ case NL80211_IFTYPE_STATION:
+ iter_data->nstations++;
break;
case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_AP:
+ iter_data->nadhocs++;
+ break;
case NL80211_IFTYPE_MESH_POINT:
- if (sc->nbcnvifs >= ATH_BCBUF) {
- ret = -ENOBUFS;
- goto out;
- }
- ic_opmode = vif->type;
+ iter_data->nmeshes++;
+ break;
+ case NL80211_IFTYPE_WDS:
+ iter_data->nwds++;
break;
default:
- ath_err(common, "Interface type %d not yet supported\n",
- vif->type);
- ret = -EOPNOTSUPP;
- goto out;
+ iter_data->nothers++;
+ break;
}
+}
- ath_dbg(common, ATH_DBG_CONFIG,
- "Attach a VIF of type: %d\n", ic_opmode);
+/* Called with sc->mutex held. */
+void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ath9k_vif_iter_data *iter_data)
+{
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ int i;
- /* Set the VIF opmode */
- avp->av_opmode = ic_opmode;
- avp->av_bslot = -1;
+ /*
+ * Use the hardware MAC address as reference, the hardware uses it
+ * together with the BSSID mask when matching addresses.
+ */
+ memset(iter_data, 0, sizeof(*iter_data));
+ iter_data->hw_macaddr = common->macaddr;
+ memset(&iter_data->mask, 0xff, ETH_ALEN);
- sc->nvifs++;
+ if (vif)
+ ath9k_vif_iter(iter_data, vif->addr, vif);
+
+ /* Get list of all active MAC addresses */
+ spin_lock_bh(&sc->wiphy_lock);
+ ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
+ iter_data);
+ for (i = 0; i < sc->num_sec_wiphy; i++) {
+ if (sc->sec_wiphy[i] == NULL)
+ continue;
+ ieee80211_iterate_active_interfaces_atomic(
+ sc->sec_wiphy[i]->hw, ath9k_vif_iter, iter_data);
+ }
+ spin_unlock_bh(&sc->wiphy_lock);
+}
+
+/* Called with sc->mutex held. */
+static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_vif_iter_data iter_data;
- ath9k_set_bssid_mask(hw, vif);
+ ath9k_calculate_iter_data(hw, vif, &iter_data);
- if (sc->nvifs > 1)
- goto out; /* skip global settings for secondary vif */
+ /* Set BSSID mask. */
+ memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+ ath_hw_setbssidmask(common);
- if (ic_opmode == NL80211_IFTYPE_AP) {
+ /* Set op-mode & TSF */
+ if (iter_data.naps > 0) {
ath9k_hw_set_tsfadjust(ah, 1);
sc->sc_flags |= SC_OP_TSF_RESET;
- }
+ ah->opmode = NL80211_IFTYPE_AP;
+ } else {
+ ath9k_hw_set_tsfadjust(ah, 0);
+ sc->sc_flags &= ~SC_OP_TSF_RESET;
- /* Set the device opmode */
- ah->opmode = ic_opmode;
+ if (iter_data.nwds + iter_data.nmeshes)
+ ah->opmode = NL80211_IFTYPE_AP;
+ else if (iter_data.nadhocs)
+ ah->opmode = NL80211_IFTYPE_ADHOC;
+ else
+ ah->opmode = NL80211_IFTYPE_STATION;
+ }
/*
* Enable MIB interrupts when there are hardware phy counters.
- * Note we only do this (at the moment) for station mode.
*/
- if ((vif->type == NL80211_IFTYPE_STATION) ||
- (vif->type == NL80211_IFTYPE_ADHOC) ||
- (vif->type == NL80211_IFTYPE_MESH_POINT)) {
+ if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) {
if (ah->config.enable_ani)
ah->imask |= ATH9K_INT_MIB;
ah->imask |= ATH9K_INT_TSFOOR;
+ } else {
+ ah->imask &= ~ATH9K_INT_MIB;
+ ah->imask &= ~ATH9K_INT_TSFOOR;
}
ath9k_hw_set_interrupts(ah, ah->imask);
- if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC) {
+ /* Set up ANI */
+ if ((iter_data.naps + iter_data.nadhocs) > 0) {
sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
+ } else {
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ del_timer_sync(&common->ani.timer);
}
+}
-out:
- mutex_unlock(&sc->mutex);
- return ret;
+/* Called with sc->mutex held, vif counts set up properly. */
+static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
+
+ ath9k_calculate_summary_state(hw, vif);
+
+ if (ath9k_uses_beacons(vif->type)) {
+ int error;
+ ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+ /* This may fail because upper levels do not have beacons
+ * properly configured yet. That's OK, we assume it
+ * will be properly configured and then we will be notified
+ * in the info_changed method and set up beacons properly
+ * there.
+ */
+ error = ath_beacon_alloc(aphy, vif);
+ if (error)
+ ath9k_reclaim_beacon(sc, vif);
+ else
+ ath_beacon_config(sc, vif);
+ }
}
-static void ath9k_reclaim_beacon(struct ath_softc *sc,
- struct ieee80211_vif *vif)
+
+static int ath9k_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
struct ath_vif *avp = (void *)vif->drv_priv;
+ int ret = 0;
- /* Disable SWBA interrupt */
- sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
- ath9k_ps_wakeup(sc);
- ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
- ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
- tasklet_kill(&sc->bcon_tasklet);
- ath9k_ps_restore(sc);
+ mutex_lock(&sc->mutex);
- ath_beacon_return(sc, avp);
- sc->sc_flags &= ~SC_OP_BEACONS;
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_MESH_POINT:
+ break;
+ default:
+ ath_err(common, "Interface type %d not yet supported\n",
+ vif->type);
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
- if (sc->nbcnvifs > 0) {
- /* Re-enable beaconing */
- sc->sc_ah->imask |= ATH9K_INT_SWBA;
- ath9k_ps_wakeup(sc);
- ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
- ath9k_ps_restore(sc);
+ if (ath9k_uses_beacons(vif->type)) {
+ if (sc->nbcnvifs >= ATH_BCBUF) {
+ ath_err(common, "Not enough beacon buffers when adding"
+ " new interface of type: %i\n",
+ vif->type);
+ ret = -ENOBUFS;
+ goto out;
+ }
+ }
+
+ if ((vif->type == NL80211_IFTYPE_ADHOC) &&
+ sc->nvifs > 0) {
+ ath_err(common, "Cannot create ADHOC interface when other"
+ " interfaces already exist.\n");
+ ret = -EINVAL;
+ goto out;
}
+
+ ath_dbg(common, ATH_DBG_CONFIG,
+ "Attach a VIF of type: %d\n", vif->type);
+
+ /* Set the VIF opmode */
+ avp->av_opmode = vif->type;
+ avp->av_bslot = -1;
+
+ sc->nvifs++;
+
+ ath9k_do_vif_add_setup(hw, vif);
+out:
+ mutex_unlock(&sc->mutex);
+ return ret;
}
static int ath9k_change_interface(struct ieee80211_hw *hw,
@@ -1487,32 +1626,33 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
mutex_lock(&sc->mutex);
- switch (new_type) {
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_ADHOC:
+ /* See if new interface type is valid. */
+ if ((new_type == NL80211_IFTYPE_ADHOC) &&
+ (sc->nvifs > 1)) {
+ ath_err(common, "When using ADHOC, it must be the only"
+ " interface.\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (ath9k_uses_beacons(new_type) &&
+ !ath9k_uses_beacons(vif->type)) {
if (sc->nbcnvifs >= ATH_BCBUF) {
ath_err(common, "No beacon slot available\n");
ret = -ENOBUFS;
goto out;
}
- break;
- case NL80211_IFTYPE_STATION:
- /* Stop ANI */
- sc->sc_flags &= ~SC_OP_ANI_RUN;
- del_timer_sync(&common->ani.timer);
- if ((vif->type == NL80211_IFTYPE_AP) ||
- (vif->type == NL80211_IFTYPE_ADHOC))
- ath9k_reclaim_beacon(sc, vif);
- break;
- default:
- ath_err(common, "Interface type %d not yet supported\n",
- vif->type);
- ret = -ENOTSUPP;
- goto out;
}
+
+ /* Clean up old vif stuff */
+ if (ath9k_uses_beacons(vif->type))
+ ath9k_reclaim_beacon(sc, vif);
+
+ /* Add new settings */
vif->type = new_type;
vif->p2p = p2p;
+ ath9k_do_vif_add_setup(hw, vif);
out:
mutex_unlock(&sc->mutex);
return ret;
@@ -1529,17 +1669,13 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
- /* Stop ANI */
- sc->sc_flags &= ~SC_OP_ANI_RUN;
- del_timer_sync(&common->ani.timer);
+ sc->nvifs--;
/* Reclaim beacon resources */
- if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
- (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
- (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT))
+ if (ath9k_uses_beacons(vif->type))
ath9k_reclaim_beacon(sc, vif);
- sc->nvifs--;
+ ath9k_calculate_summary_state(hw, NULL);
mutex_unlock(&sc->mutex);
}
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index ea2f67c..8def8c2 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -589,8 +589,14 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
return;
mgmt = (struct ieee80211_mgmt *)skb->data;
- if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0)
+ if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) {
+ /* TODO: This doesn't work well if you have stations
+ * associated to two different APs because curbssid
+ * is just the last AP that any of the stations associated
+ * with.
+ */
return; /* not from our current AP */
+ }
sc->ps_flags &= ~PS_WAIT_FOR_BEACON;
@@ -985,8 +991,14 @@ static void ath9k_process_rssi(struct ath_common *common,
fc = hdr->frame_control;
if (!ieee80211_is_beacon(fc) ||
- compare_ether_addr(hdr->addr3, common->curbssid))
+ compare_ether_addr(hdr->addr3, common->curbssid)) {
+ /* TODO: This doesn't work well if you have stations
+ * associated to two different APs because curbssid
+ * is just the last AP that any of the stations associated
+ * with.
+ */
return;
+ }
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c
index 2dc7095..d205c66 100644
--- a/drivers/net/wireless/ath/ath9k/virtual.c
+++ b/drivers/net/wireless/ath/ath9k/virtual.c
@@ -18,54 +18,6 @@
#include "ath9k.h"
-struct ath9k_vif_iter_data {
- const u8 *hw_macaddr;
- u8 mask[ETH_ALEN];
-};
-
-static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
- struct ath9k_vif_iter_data *iter_data = data;
- int i;
-
- for (i = 0; i < ETH_ALEN; i++)
- iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
-}
-
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct ath_wiphy *aphy = hw->priv;
- struct ath_softc *sc = aphy->sc;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath9k_vif_iter_data iter_data;
- int i;
-
- /*
- * Use the hardware MAC address as reference, the hardware uses it
- * together with the BSSID mask when matching addresses.
- */
- iter_data.hw_macaddr = common->macaddr;
- memset(&iter_data.mask, 0xff, ETH_ALEN);
-
- if (vif)
- ath9k_vif_iter(&iter_data, vif->addr, vif);
-
- /* Get list of all active MAC addresses */
- spin_lock_bh(&sc->wiphy_lock);
- ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
- &iter_data);
- for (i = 0; i < sc->num_sec_wiphy; i++) {
- if (sc->sec_wiphy[i] == NULL)
- continue;
- ieee80211_iterate_active_interfaces_atomic(
- sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data);
- }
- spin_unlock_bh(&sc->wiphy_lock);
-
- memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
- ath_hw_setbssidmask(common);
-}
-
int ath9k_wiphy_add(struct ath_softc *sc)
{
int i, error;
--
1.7.2.3
^ permalink raw reply related
* Re: [Driver] NEC WL300NU-G
From: Gertjan van Wingerde @ 2011-01-15 17:39 UTC (permalink / raw)
To: u2@whoplays.asia; +Cc: linux-wireless
In-Reply-To: <4D31C1F5.7080306@whoplays.asia>
On 01/15/11 16:49, u2@whoplays.asia wrote:
> hi,
>
> According to the list linuxwireless.org/en/users/Devices/USB, Wireless USB adapter NEC WL300NU-G[0x409:0x093f] is supported by ar9170usb.
>
> But the one I bought via www.amazon.co.jp/NEC-Aterm-WL300NU-G-PA-WL300NU-G is [0x409:0x0249] and not detected by any drivers...
>
> $ lsusb
> Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
> Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
> Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
> Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
> Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
> Bus 002 Device 006: ID 0a5c:2101 Broadcom Corp. Bluetooth Controller
> Bus 002 Device 005: ID 0853:0100 Topre Corporation HHKB Professional
> Bus 002 Device 004: ID 0409:005a NEC Corp. HighSpeed Hub
> Bus 002 Device 003: ID 0409:0249 NEC Corp.
> Bus 002 Device 002: ID 2019:ab50 PLANEX GW-US54Mini2
> Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
> Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
> $ uname -a
> Linux localhost 2.6.32-5-amd64 #1 SMP Wed Jan 12 03:40:32 UTC 2011 x86_64 GNU/Linux
>
> Plz anyone describe me why this one has another vendor-productID, and will this one supported?
It looks like this device is supported in the latest ar9170usb driver. I can't really find in which kernel
release support for this device has been added, but I'm almost certain that this was after 2.6.32 had been
released (it is more likely that 2.6.34 is the first kernel release that supports your device).
In other words, the kernel version that you are testing with is simply too old to support the device.
I guess you need to upgrade to a later kernel version (or use compat-wireless).
---
Gertjan.
^ permalink raw reply
* [Driver] NEC WL300NU-G
From: u2 @ 2011-01-15 15:49 UTC (permalink / raw)
To: linux-wireless
hi,
According to the list linuxwireless.org/en/users/Devices/USB, Wireless
USB adapter NEC WL300NU-G[0x409:0x093f] is supported by ar9170usb.
But the one I bought via
www.amazon.co.jp/NEC-Aterm-WL300NU-G-PA-WL300NU-G is [0x409:0x0249] and
not detected by any drivers...
$ lsusb
Bus 007 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 006: ID 0a5c:2101 Broadcom Corp. Bluetooth Controller
Bus 002 Device 005: ID 0853:0100 Topre Corporation HHKB Professional
Bus 002 Device 004: ID 0409:005a NEC Corp. HighSpeed Hub
Bus 002 Device 003: ID 0409:0249 NEC Corp.
Bus 002 Device 002: ID 2019:ab50 PLANEX GW-US54Mini2
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
$ uname -a
Linux localhost 2.6.32-5-amd64 #1 SMP Wed Jan 12 03:40:32 UTC 2011
x86_64 GNU/Linux
Plz anyone describe me why this one has another vendor-productID, and
will this one supported?
Regards,
Miyagi
^ permalink raw reply
* Re: [ath9k-devel] [RFC 1/2] ath9k: Fix up hardware mode and beacons with multiple vifs.
From: Ben Greear @ 2011-01-15 14:54 UTC (permalink / raw)
To: Björn Smedman; +Cc: Felix Fietkau, linux-wireless, ath9k-devel
In-Reply-To: <AANLkTimAxXKiM_wBToLXfBxfwF1xbi+KZVHTQE-6fc0i@mail.gmail.com>
On 01/14/2011 05:41 PM, Björn Smedman wrote:
> On Fri, Jan 14, 2011 at 7:05 PM, Felix Fietkau<nbd@openwrt.org> wrote:
>> Do we really need all those counters? Wouldn't it be better to iterate over
>> active interfaces instead?
>
> I think iterating over active interfaces is better, especially if we
> set up more fine-graned ah-> variables that make sense in themselves
> for stuff like power save and tsf sync. But that's just my two cents.
>
> As an example of something that may be more or less impossible to do
> without iteration consider multiple vifs with different beacon
> intervals. This could be handled by computing a greatest common
> devisor of all beacon intervals and using this for SWBA.
We already iterate when setting the bssid mask. I could have that
method calculate the vif counts with little extra cost. I want to avoid any more
linear iterations over the interface list if possible, so hopefully
I can re-use that one iteration and not add more...
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [PATCH] mac80211: drop non-auth 3-addr data frames when running as a 4-addr station
From: Felix Fietkau @ 2011-01-15 13:38 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, johannes, Felix Fietkau
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) &&
+ sdata->vif.type == NL80211_IFTYPE_STATION &&
+ !!sdata->u.mgd.use_4addr != !!ieee80211_has_a4(hdr->frame_control))
+ return -1;
+
if (is_multicast_ether_addr(hdr->addr1) &&
- ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) ||
- (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr)))
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta)
return -1;
return ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
--
1.7.3.2
^ permalink raw reply related
* Re: BUG in rt2x00lib_txdone() with 2.6.37-rc8
From: Ivo Van Doorn @ 2011-01-15 13:34 UTC (permalink / raw)
To: Helmut Schaa; +Cc: Ingo Brunberg, linux-kernel, linux-wireless
In-Reply-To: <201101131423.51640.helmut.schaa@googlemail.com>
Hi,
> Just a shot in the dark but since the stack trace shows the newly added
> watchdog this might be the result of a race between a regular txdone work
> (mac80211 workqueue) vs the watchdog work (global workqueue).
>
> I guess the following situation could happen:
> A regular tx done work calls rt2x00lib_txdone which first sets entry->skb to
> NULL, calls the driver specific clear_entry and afterwards increases
> Q_INDEX_DONE. If the watchdog work calls rt2x00lib_txdone on a different CPU
> inbetween the skb might be NULL and cause the above oops.
This could be, would be interesting to know if compat-wireless also shows
this problem. Because the queue refactoring code which should have solved
these race conditions was added after 2.6.37.
Ivo
^ permalink raw reply
* [PATCH 1/2] ath9k: try more than one tid when scheduling a new aggregate
From: Felix Fietkau @ 2011-01-15 13:30 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, lrodriguez, Felix Fietkau
Sometimes the first TID in the first AC's list is not available for forming
a new aggregate (the BAW might not allow it), however other TIDs may have
data available for sending.
Prevent a slowdown of other TIDs by going through multiple entries until
we've either hit the last one or enough AMPDUs are pending in the hardware
queue.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/xmit.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index ab4f7b4..fffd13d 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1224,12 +1224,14 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
{
struct ath_atx_ac *ac;
- struct ath_atx_tid *tid;
+ struct ath_atx_tid *tid, *last;
- if (list_empty(&txq->axq_acq))
+ if (list_empty(&txq->axq_acq) ||
+ txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
return;
ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
+ last = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
list_del(&ac->list);
ac->sched = false;
@@ -1253,7 +1255,8 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
if (!list_empty(&tid->buf_q))
ath_tx_queue_tid(txq, tid);
- break;
+ if (tid == last || txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+ break;
} while (!list_empty(&ac->tid_q));
if (!list_empty(&ac->tid_q)) {
--
1.7.3.2
^ permalink raw reply related
* [PATCH 2/2] ath9k: fix excessive BAR sending when a frame exceeds its retry limit
From: Felix Fietkau @ 2011-01-15 13:30 UTC (permalink / raw)
To: linux-wireless; +Cc: linville, lrodriguez, Felix Fietkau
In-Reply-To: <1295098215-98910-1-git-send-email-nbd@openwrt.org>
Because the sendbar variable was not reset to zero, the stack would send
Block ACK requests for all subframes following the one that failed, which
could mess up the receiver side block ack window.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/xmit.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index fffd13d..ad569e1 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -429,7 +429,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
while (bf) {
- txfail = txpending = 0;
+ txfail = txpending = sendbar = 0;
bf_next = bf->bf_next;
skb = bf->bf_mpdu;
--
1.7.3.2
^ permalink raw reply related
* Re: [ath9k-devel] [RFC 1/2] ath9k: Fix up hardware mode and beacons with multiple vifs.
From: Jouni Malinen @ 2011-01-15 11:07 UTC (permalink / raw)
To: Björn Smedman; +Cc: sbrown, greearb, ath9k-devel, linux-wireless
In-Reply-To: <AANLkTi=_qAB6aVEbsTBUfpVwTg4GbLsAYbyP0PA2n+NO@mail.gmail.com>
On Sat, Jan 15, 2011 at 02:20:00AM +0100, Björn Smedman wrote:
> 2011/1/15 Steve Brown <sbrown@cortland.com>:
> > For instance, an ap vif has a ~100ms interval and a mesh vif has a
> > ~1000ms interval. I don't see how to avoid a per vif interval.
>
> I agree. We should fix ath9k so it works correctly even if beacon
> interval is different for different vifs (within some reasonable
> limits).
Yes, up to a limit. Handling something like 100 TU on one vif and 1000
TU on another is fine, but something like 100 TU and 103 TU would need
to be forced to use the same interval. I've been thinking of adding some
kind of mechanism for the driver to override Beacon interval in such
cases (which would need to go back all the way to user space to hostapd
in case of AP mode).
--
Jouni Malinen PGP id EFC895FA
^ permalink raw reply
* Re: [PATCH] mwifiex: remove duplicated NULL checks
From: Julian Calaby @ 2011-01-15 2:59 UTC (permalink / raw)
To: Bing Zhao
Cc: linux-wireless, John W. Linville, Johannes Berg, Amitkumar Karwar,
Kiran Divekar, Frank Huang
In-Reply-To: <1295033760-31108-1-git-send-email-bzhao@marvell.com>
On Sat, Jan 15, 2011 at 06:36, Bing Zhao <bzhao@marvell.com> wrote:
> From: Amitkumar Karwar <akarwar@marvell.com>
>
> Some functions have unnecessory NULL check for an input parameter
> because the caller to those functions is already checking the parameter
> for NULL before calling them.
It may be more readable and efficient to eliminate the NULL checks in
the callers - and adjust the code to inform the callers of the case
where the pointer passed is null and make the callers to properly
handle this case.
This should also make the driver more robust as failures can be passed
up the stack to places that can deal with them more effectively than
just printing a message.
Thanks,
--
Julian Calaby
Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/
.Plan: http://sites.google.com/site/juliancalaby/
^ permalink raw reply
* Re: [ath9k-devel] [RFC 1/2] ath9k: Fix up hardware mode and beacons with multiple vifs.
From: Björn Smedman @ 2011-01-15 1:41 UTC (permalink / raw)
To: Felix Fietkau; +Cc: greearb, linux-wireless, ath9k-devel
In-Reply-To: <4D309086.7070703@openwrt.org>
On Fri, Jan 14, 2011 at 7:05 PM, Felix Fietkau <nbd@openwrt.org> wrote:
> Do we really need all those counters? Wouldn't it be better to iterate over
> active interfaces instead?
I think iterating over active interfaces is better, especially if we
set up more fine-graned ah-> variables that make sense in themselves
for stuff like power save and tsf sync. But that's just my two cents.
As an example of something that may be more or less impossible to do
without iteration consider multiple vifs with different beacon
intervals. This could be handled by computing a greatest common
devisor of all beacon intervals and using this for SWBA.
/Björn
^ permalink raw reply
* Re: [ath9k-devel] [RFC 1/2] ath9k: Fix up hardware mode and beacons with multiple vifs.
From: Björn Smedman @ 2011-01-15 1:20 UTC (permalink / raw)
To: sbrown; +Cc: greearb, ath9k-devel, linux-wireless
In-Reply-To: <1295052936.2253.5.camel@mythtv.ewol.com>
2011/1/15 Steve Brown <sbrown@cortland.com>:
> On Sat, 2011-01-15 at 00:19 +0100, Björn Smedman wrote:
>> This is another comment that is a little out of place but when I see
>> the identifier beacon_interval in this context I cannot help bringing
>> up per-vif settings as a related problem: If I read the code (or
>> rather the lack of code) correctly the beacon interval of the last (or
>> first?) beaconing vif added will be used to set up beacon tx, whereas
>> the actual beacon contents will reflect the beacon intervals
>> configured for individual vifs which may all be different... The same
>> goes for e.g. tx queue configuration, no?
[snip]
> For instance, an ap vif has a ~100ms interval and a mesh vif has a
> ~1000ms interval. I don't see how to avoid a per vif interval.
I agree. We should fix ath9k so it works correctly even if beacon
interval is different for different vifs (within some reasonable
limits).
In the mean time, as a workaround, try to configure the same beacon
interval for all vifs.
/Björn
^ permalink raw reply
* Re: [ath9k-devel] [RFC 1/2] ath9k: Fix up hardware mode and beacons with multiple vifs.
From: Steve Brown @ 2011-01-15 0:55 UTC (permalink / raw)
To: Björn Smedman; +Cc: greearb, ath9k-devel, linux-wireless
In-Reply-To: <AANLkTi=WTUiy1DYNhE12_KZp8QFUrWebY2Cpzud5P0b3@mail.gmail.com>
On Sat, 2011-01-15 at 00:19 +0100, Björn Smedman wrote:
> Thank you for your efforts to get multi-vifs working better.
>
> This is another comment that is a little out of place but when I see
> the identifier beacon_interval in this context I cannot help bringing
> up per-vif settings as a related problem: If I read the code (or
> rather the lack of code) correctly the beacon interval of the last (or
> first?) beaconing vif added will be used to set up beacon tx, whereas
> the actual beacon contents will reflect the beacon intervals
> configured for individual vifs which may all be different... The same
> goes for e.g. tx queue configuration, no?
>
> It feels like we need a general multi-vif cleanup here but it's too
> big for me unfortunately.
>
> /Björn
> _______________________________________________
For instance, an ap vif has a ~100ms interval and a mesh vif has a
~1000ms interval. I don't see how to avoid a per vif interval.
Steve
^ permalink raw reply
* htc dream wl1251 and MSM_GPIO_TO_INT(29)
From: Denis 'GNUtoo' Carikli @ 2011-01-14 23:33 UTC (permalink / raw)
To: Kalle Valo; +Cc: Grazvydas Ignotas, linux-wireless, Bob Copeland
hi,
In the TI driver available here:
http://android.git.kernel.org/?p=platform/system/wlan/ti.git;a=blob;f=sta_dk_4_0_4_32/pform/linux/src/esta_drv.c;h=a968e20bebf6c22f9983d0a6db50b40f04f1f1e8;hb=refs/heads/froyo
there is:
#define TROUT_IRQ MSM_GPIO_TO_INT(29)
[...]
if (drv->irq)
[...]
if ((rc = request_irq (drv->irq, (irq_handler_t)tiwlan_interrupt,
IRQF_SHARED | IRQF_TRIGGER_FALLING /*Dm:*/, drv->netdev->name,
drv))){//error message}
[...]
set_irq_type (drv->irq, IRQ_TYPE_EDGE_FALLING);
[...]
disable_irq (drv->irq);
So we learn several things here:
*it uses MSM_GPIO_TO_INT(29)
*the irq configuration.
So I took the 2.6.32 kernel version available here:
http://gitorious.org/htc-msm-2-6-32/leviathan-incoming/commits/android-msm-2.6.32-rebase
I also took an old compat-wireless driver(because more recent ones have
the runtime PM capability and I don't know how to make it work with an
old 2.6.32 kernel that lacks such patches)
The version is this one compat-wireless-2010-10-04
I modified both the kernel and compat wireless to be able to pass the
wl12xx struct directly, like in recent kernels, and it seem to work.
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;
trout_wl1251_pdata.use_eeprom = false;
ret = wl12xx_set_platform_data(&trout_wl1251_pdata);
if (ret < 0)
goto fail_irq;
fail_irq:
printk("trout wifi GPIO failed\n");
gpio_free(TROUT_WIFI_IRQ_GPIO);
}
The data is beeing passed(else it wouldn't freesze) and the phone
freezes.
note that the compat wireless irq handling code is different from the ti
driver:
if (wl->irq) {
ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
if (ret < 0) {
wl1251_error("request_irq() failed: %d", ret);
goto disable;
}
set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
disable_irq(wl->irq);
wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
wl1251_info("using dedicated interrupt line");
}
in the TI driver there is IRQ_TYPE_EDGE_FALLING while here there is
IRQ_TYPE_EDGE_RISING.
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)?
Denis.
^ permalink raw reply
* [PATCH v2] ath9k: Fix up hardware mode and beacons with multiple vifs.
From: greearb @ 2011-01-14 23:34 UTC (permalink / raw)
To: linux-wireless; +Cc: ath9k-devel, Ben Greear
From: Ben Greear <greearb@candelatech.com>
When using a mixture of AP and Station interfaces,
the hardware mode was using the type of the
last VIF registered. Instead, we should keep track
of the number of different types of vifs and set the
mode accordingly.
In addtion, use the vif type instead of hardware opmode
when dealing with beacons.
Attempt to move some of the common setup code into smaller
methods so we can re-use it when changing vif mode as
well as adding/deleting vifs.
Signed-off-by: Ben Greear <greearb@candelatech.com>
---
v1 -> v2: Use only ADHOC, AP, and STATION opmodes.
Set up tsf and ani based on current existing
vifs instead of depending on opmode.
Remove spurious 'TODO' comment that did not apply.
:100644 100644 3108699... a2da259... M drivers/net/wireless/ath/ath9k/ath9k.h
:100644 100644 385ba03... 8de591e... M drivers/net/wireless/ath/ath9k/beacon.c
:100644 100644 0452580... 3845832... M drivers/net/wireless/ath/ath9k/main.c
:100644 100644 ea2f67c... 8def8c2... M drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/ath9k/ath9k.h | 10 +-
drivers/net/wireless/ath/ath9k/beacon.c | 14 +-
drivers/net/wireless/ath/ath9k/main.c | 284 +++++++++++++++++++++----------
drivers/net/wireless/ath/ath9k/recv.c | 16 ++-
4 files changed, 224 insertions(+), 100 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 3108699..a2da259 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -607,10 +607,15 @@ struct ath_softc {
u32 sc_flags; /* SC_OP_* */
u16 ps_flags; /* PS_* */
u16 curtxpow;
- u8 nbcnvifs;
- u16 nvifs;
bool ps_enabled;
bool ps_idle;
+ short nbcnvifs;
+ short nvifs;
+ short naps; /* number of APs */
+ short nmeshes;
+ short nstations;
+ short nwds;
+ short nadhocs;
unsigned long ps_usecount;
struct ath_config config;
@@ -694,6 +699,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
+bool ath9k_uses_beacons(int type);
#ifdef CONFIG_PCI
int ath_pci_init(void);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 385ba03..8de591e 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -244,9 +244,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
struct ath_buf, list);
list_del(&avp->av_bcbuf->list);
- if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
- sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC ||
- sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+ if (ath9k_uses_beacons(vif->type)) {
int slot;
/*
* Assign the vif to a beacon xmit slot. As
@@ -282,7 +280,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
/* NB: the beacon data buffer must be 32-bit aligned. */
skb = ieee80211_beacon_get(sc->hw, vif);
if (skb == NULL) {
- ath_dbg(common, ATH_DBG_BEACON, "cannot get skb\n");
+ ath_err(common, "ieee80211_beacon_get failed\n");
return -ENOMEM;
}
@@ -720,10 +718,10 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
iftype = sc->sc_ah->opmode;
}
- cur_conf->listen_interval = 1;
- cur_conf->dtim_count = 1;
- cur_conf->bmiss_timeout =
- ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
+ cur_conf->listen_interval = 1;
+ cur_conf->dtim_count = 1;
+ cur_conf->bmiss_timeout =
+ ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
/*
* It looks like mac80211 may end up using beacon interval of zero in
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 0452580..3845832 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1366,112 +1366,217 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
}
-static int ath9k_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void decrement_vif_type(struct ath_softc *sc, int type)
{
- struct ath_wiphy *aphy = hw->priv;
- struct ath_softc *sc = aphy->sc;
- struct ath_hw *ah = sc->sc_ah;
- struct ath_common *common = ath9k_hw_common(ah);
- struct ath_vif *avp = (void *)vif->drv_priv;
- enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
- int ret = 0;
-
- mutex_lock(&sc->mutex);
-
- switch (vif->type) {
+ switch (type) {
+ case NL80211_IFTYPE_AP:
+ sc->naps--;
+ break;
case NL80211_IFTYPE_STATION:
- ic_opmode = NL80211_IFTYPE_STATION;
+ sc->nstations--;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ sc->nadhocs--;
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ sc->nmeshes--;
break;
case NL80211_IFTYPE_WDS:
- ic_opmode = NL80211_IFTYPE_WDS;
+ sc->nwds--;
break;
- case NL80211_IFTYPE_ADHOC:
+ }
+}
+
+static void increment_vif_type(struct ath_softc *sc, int type)
+{
+ switch (type) {
case NL80211_IFTYPE_AP:
+ sc->naps++;
+ break;
+ case NL80211_IFTYPE_STATION:
+ sc->nstations++;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ sc->nadhocs++;
+ break;
case NL80211_IFTYPE_MESH_POINT:
- if (sc->nbcnvifs >= ATH_BCBUF) {
- ret = -ENOBUFS;
- goto out;
- }
- ic_opmode = vif->type;
+ sc->nmeshes++;
+ break;
+ case NL80211_IFTYPE_WDS:
+ sc->nwds++;
break;
+ }
+}
+
+bool ath9k_uses_beacons(int type)
+{
+ switch (type) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ return true;
default:
- ath_err(common, "Interface type %d not yet supported\n",
- vif->type);
- ret = -EOPNOTSUPP;
- goto out;
+ return false;
}
+}
- ath_dbg(common, ATH_DBG_CONFIG,
- "Attach a VIF of type: %d\n", ic_opmode);
+static void ath9k_reclaim_beacon(struct ath_softc *sc,
+ struct ieee80211_vif *vif)
+{
+ struct ath_vif *avp = (void *)vif->drv_priv;
- /* Set the VIF opmode */
- avp->av_opmode = ic_opmode;
- avp->av_bslot = -1;
+ /* Disable SWBA interrupt */
+ sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
+ ath9k_ps_wakeup(sc);
+ ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
+ ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+ tasklet_kill(&sc->bcon_tasklet);
+ ath9k_ps_restore(sc);
- sc->nvifs++;
+ ath_beacon_return(sc, avp);
+ sc->sc_flags &= ~SC_OP_BEACONS;
- ath9k_set_bssid_mask(hw, vif);
+ if (sc->nbcnvifs > 0) {
+ /* Re-enable beaconing */
+ sc->sc_ah->imask |= ATH9K_INT_SWBA;
+ ath9k_ps_wakeup(sc);
+ ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
+ ath9k_ps_restore(sc);
+ }
+}
- if (sc->nvifs > 1)
- goto out; /* skip global settings for secondary vif */
+/* Called with sc->mutex held, vif counts set up properly. */
+static void ath9k_calculate_opmode(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
- if (ic_opmode == NL80211_IFTYPE_AP) {
+ if (sc->naps > 0) {
ath9k_hw_set_tsfadjust(ah, 1);
sc->sc_flags |= SC_OP_TSF_RESET;
- }
+ ah->opmode = NL80211_IFTYPE_AP;
+ } else {
+ ath9k_hw_set_tsfadjust(ah, 0);
+ sc->sc_flags &= ~SC_OP_TSF_RESET;
- /* Set the device opmode */
- ah->opmode = ic_opmode;
+ if (sc->nwds + sc->nmeshes)
+ ah->opmode = NL80211_IFTYPE_AP;
+ else if (sc->nadhocs)
+ ah->opmode = NL80211_IFTYPE_ADHOC;
+ else
+ ah->opmode = ah->opmode = NL80211_IFTYPE_STATION;
+ }
/*
* Enable MIB interrupts when there are hardware phy counters.
- * Note we only do this (at the moment) for station mode.
*/
- if ((vif->type == NL80211_IFTYPE_STATION) ||
- (vif->type == NL80211_IFTYPE_ADHOC) ||
- (vif->type == NL80211_IFTYPE_MESH_POINT)) {
+ if ((sc->nstations + sc->nadhocs + sc->nmeshes) > 0) {
if (ah->config.enable_ani)
ah->imask |= ATH9K_INT_MIB;
ah->imask |= ATH9K_INT_TSFOOR;
+ } else {
+ ah->imask &= ~ATH9K_INT_MIB;
+ ah->imask &= ~ATH9K_INT_TSFOOR;
}
ath9k_hw_set_interrupts(ah, ah->imask);
- if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_ADHOC) {
+ if ((sc->naps + sc->nadhocs) > 0) {
sc->sc_flags |= SC_OP_ANI_RUN;
ath_start_ani(common);
+ } else {
+ sc->sc_flags &= ~SC_OP_ANI_RUN;
+ del_timer_sync(&common->ani.timer);
}
+}
-out:
- mutex_unlock(&sc->mutex);
- return ret;
+/* Called with sc->mutex held, vif counts set up properly. */
+static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
+
+ ath9k_calculate_opmode(sc);
+
+ ath9k_set_bssid_mask(hw, vif);
+
+ if (ath9k_uses_beacons(vif->type)) {
+ int error;
+ ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+ /* This may fail because upper levels do not have beacons
+ * properly configured yet. That's OK, we assume it
+ * will be properly configured and then we will be notified
+ * in the info_changed method and set up beacons properly
+ * there.
+ */
+ error = ath_beacon_alloc(aphy, vif);
+ if (error)
+ ath9k_reclaim_beacon(sc, vif);
+ else
+ ath_beacon_config(sc, vif);
+ }
}
-static void ath9k_reclaim_beacon(struct ath_softc *sc,
- struct ieee80211_vif *vif)
+
+static int ath9k_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
+ struct ath_wiphy *aphy = hw->priv;
+ struct ath_softc *sc = aphy->sc;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
struct ath_vif *avp = (void *)vif->drv_priv;
+ int ret = 0;
- /* Disable SWBA interrupt */
- sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
- ath9k_ps_wakeup(sc);
- ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
- ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
- tasklet_kill(&sc->bcon_tasklet);
- ath9k_ps_restore(sc);
+ mutex_lock(&sc->mutex);
- ath_beacon_return(sc, avp);
- sc->sc_flags &= ~SC_OP_BEACONS;
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_WDS:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_MESH_POINT:
+ break;
+ default:
+ ath_err(common, "Interface type %d not yet supported\n",
+ vif->type);
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
- if (sc->nbcnvifs > 0) {
- /* Re-enable beaconing */
- sc->sc_ah->imask |= ATH9K_INT_SWBA;
- ath9k_ps_wakeup(sc);
- ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
- ath9k_ps_restore(sc);
+ if (ath9k_uses_beacons(vif->type)) {
+ if (sc->nbcnvifs >= ATH_BCBUF) {
+ ath_err(common, "Not enough beacon buffers when adding"
+ " new interface of type: %i\n",
+ vif->type);
+ ret = -ENOBUFS;
+ goto out;
+ }
}
+
+ if ((vif->type == NL80211_IFTYPE_ADHOC) &&
+ sc->nvifs > 0) {
+ ath_err(common, "Cannot create ADHOC interface when other"
+ " interfaces already exist.\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ath_dbg(common, ATH_DBG_CONFIG,
+ "Attach a VIF of type: %d\n", vif->type);
+
+ /* Set the VIF opmode */
+ avp->av_opmode = vif->type;
+ avp->av_bslot = -1;
+
+ increment_vif_type(sc, vif->type);
+ sc->nvifs++;
+
+ ath9k_do_vif_add_setup(hw, vif);
+out:
+ mutex_unlock(&sc->mutex);
+ return ret;
}
static int ath9k_change_interface(struct ieee80211_hw *hw,
@@ -1487,32 +1592,36 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
mutex_lock(&sc->mutex);
- switch (new_type) {
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_ADHOC:
+ /* See if new interface type is valid. */
+ if ((new_type == NL80211_IFTYPE_ADHOC) &&
+ (sc->nvifs > 1)) {
+ ath_err(common, "When using ADHOC, it must be the only"
+ " interface.\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (ath9k_uses_beacons(new_type) &&
+ !ath9k_uses_beacons(vif->type)) {
if (sc->nbcnvifs >= ATH_BCBUF) {
ath_err(common, "No beacon slot available\n");
ret = -ENOBUFS;
goto out;
}
- break;
- case NL80211_IFTYPE_STATION:
- /* Stop ANI */
- sc->sc_flags &= ~SC_OP_ANI_RUN;
- del_timer_sync(&common->ani.timer);
- if ((vif->type == NL80211_IFTYPE_AP) ||
- (vif->type == NL80211_IFTYPE_ADHOC))
- ath9k_reclaim_beacon(sc, vif);
- break;
- default:
- ath_err(common, "Interface type %d not yet supported\n",
- vif->type);
- ret = -ENOTSUPP;
- goto out;
}
+
+ /* Clean up old vif stuff, check for adding interface. */
+ decrement_vif_type(sc, vif->type);
+
+ if (ath9k_uses_beacons(vif->type))
+ ath9k_reclaim_beacon(sc, vif);
+
+ /* Add new settings */
vif->type = new_type;
vif->p2p = p2p;
+ increment_vif_type(sc, vif->type);
+ ath9k_do_vif_add_setup(hw, vif);
out:
mutex_unlock(&sc->mutex);
return ret;
@@ -1529,17 +1638,16 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
- /* Stop ANI */
- sc->sc_flags &= ~SC_OP_ANI_RUN;
- del_timer_sync(&common->ani.timer);
+ decrement_vif_type(sc, vif->type);
+ sc->nvifs--;
/* Reclaim beacon resources */
- if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
- (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
- (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT))
+ if (ath9k_uses_beacons(vif->type))
ath9k_reclaim_beacon(sc, vif);
- sc->nvifs--;
+ ath9k_calculate_opmode(sc);
+
+ ath9k_set_bssid_mask(hw, NULL);
mutex_unlock(&sc->mutex);
}
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index ea2f67c..8def8c2 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -589,8 +589,14 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
return;
mgmt = (struct ieee80211_mgmt *)skb->data;
- if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0)
+ if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) {
+ /* TODO: This doesn't work well if you have stations
+ * associated to two different APs because curbssid
+ * is just the last AP that any of the stations associated
+ * with.
+ */
return; /* not from our current AP */
+ }
sc->ps_flags &= ~PS_WAIT_FOR_BEACON;
@@ -985,8 +991,14 @@ static void ath9k_process_rssi(struct ath_common *common,
fc = hdr->frame_control;
if (!ieee80211_is_beacon(fc) ||
- compare_ether_addr(hdr->addr3, common->curbssid))
+ compare_ether_addr(hdr->addr3, common->curbssid)) {
+ /* TODO: This doesn't work well if you have stations
+ * associated to two different APs because curbssid
+ * is just the last AP that any of the stations associated
+ * with.
+ */
return;
+ }
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
--
1.7.2.3
^ permalink raw reply related
* Re: [RFC 1/2] ath9k: Fix up hardware mode and beacons with multiple vifs.
From: Ben Greear @ 2011-01-14 23:24 UTC (permalink / raw)
To: Björn Smedman; +Cc: linux-wireless, ath9k-devel
In-Reply-To: <AANLkTi=WTUiy1DYNhE12_KZp8QFUrWebY2Cpzud5P0b3@mail.gmail.com>
On 01/14/2011 03:19 PM, Björn Smedman wrote:
> On Fri, Jan 14, 2011 at 6:27 PM,<greearb@candelatech.com> wrote:
>> From: Ben Greear<greearb@candelatech.com>
>>
>> When using a mixture of AP and Station interfaces,
>> the hardware mode was using the type of the
>> last VIF registered. Instead, we should keep track
>> of the number of different types of vifs and set the
>> mode accordingly.
>
> Thank you for your efforts to get multi-vifs working better.
>
> This is another comment that is a little out of place but when I see
> the identifier beacon_interval in this context I cannot help bringing
> up per-vif settings as a related problem: If I read the code (or
> rather the lack of code) correctly the beacon interval of the last (or
> first?) beaconing vif added will be used to set up beacon tx, whereas
> the actual beacon contents will reflect the beacon intervals
> configured for individual vifs which may all be different... The same
> goes for e.g. tx queue configuration, no?
>
> It feels like we need a general multi-vif cleanup here but it's too
> big for me unfortunately.
I haven't looked at beacons in that detail yet.
If I can get agreement on the current patch (and the dozen or so preceding it),
then I can take a closer look at beacon intervals. I don't think that needs to
be done as part of this vif/opmode/beaconing cleanup though.
New patch is coming shortly, as soon as I get some testing completed.
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: [RFC 1/2] ath9k: Fix up hardware mode and beacons with multiple vifs.
From: Björn Smedman @ 2011-01-14 23:19 UTC (permalink / raw)
To: greearb; +Cc: linux-wireless, ath9k-devel
In-Reply-To: <1295026029-21130-1-git-send-email-greearb@candelatech.com>
On Fri, Jan 14, 2011 at 6:27 PM, <greearb@candelatech.com> wrote:
> From: Ben Greear <greearb@candelatech.com>
>
> When using a mixture of AP and Station interfaces,
> the hardware mode was using the type of the
> last VIF registered. Instead, we should keep track
> of the number of different types of vifs and set the
> mode accordingly.
Thank you for your efforts to get multi-vifs working better.
This is another comment that is a little out of place but when I see
the identifier beacon_interval in this context I cannot help bringing
up per-vif settings as a related problem: If I read the code (or
rather the lack of code) correctly the beacon interval of the last (or
first?) beaconing vif added will be used to set up beacon tx, whereas
the actual beacon contents will reflect the beacon intervals
configured for individual vifs which may all be different... The same
goes for e.g. tx queue configuration, no?
It feels like we need a general multi-vif cleanup here but it's too
big for me unfortunately.
/Björn
^ permalink raw reply
* Re: 5GHz 802.11n USB Adapter
From: Jason Andryuk @ 2011-01-14 23:07 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <AANLkTimj11OJRbjO2GBn=C36D7UDUURvguERS5XYoJ7W@mail.gmail.com>
On Sat, Jan 8, 2011 at 2:21 PM, Jason Andryuk <jandryuk@gmail.com> wrote:
> I am looking for a linux-supported dual band 802.11n USB Adapter that
> can operate at both 2.4GHz and 5GHz.
I was hoping for a little more feedback on the status of different drivers.
In the meantime, I found http://www.wikidevi.com/ which has lots of
info on the chipsets used with various wireless adapters.
Specifically http://www.wikidevi.com/wiki/Special:BrowseData which
allow one to search by way of various parameters.
Hopefully others find the above site helpful.
Jason
^ permalink raw reply
* Re: [RFC] ath9k: Handle interface changes properly
From: Björn Smedman @ 2011-01-14 23:02 UTC (permalink / raw)
To: Felix Fietkau; +Cc: Rajkumar Manoharan, linux-wireless@vger.kernel.org
In-Reply-To: <4D309EC2.2060409@openwrt.org>
On Fri, Jan 14, 2011 at 8:06 PM, Felix Fietkau <nbd@openwrt.org> wrote:
> I think that when we use ah->opmode, we should only use it for very generic
> operating modes:
>
> AP: no TSF sync, beacon tx can be enabled.
> ADHOC: TSF sync against IBSS cell, beacon tx can be enabled
> STATION: TSF sync against one AP, only station beacon timers for PS.
>
> Only the above distinctions are relevant for ath9k_hw, everything else is
> handled by the driver/stack. There is no reason for adding extra checks to
> ath9k_hw for mesh and WDS, since they work best with ah->opmode set to AP,
> and there is nothing extra on the *hardware* side that should be configured
> there via a different opmode. That's why I think leaking the mac80211
> interface types to ath9k_hw is a bad idea.
Isn't that also a good argument against using nl80211_iftype in this
context? The values currently defined are:
* @NL80211_IFTYPE_ADHOC: independent BSS member
* @NL80211_IFTYPE_STATION: managed BSS member
* @NL80211_IFTYPE_AP: access point
* @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points
* @NL80211_IFTYPE_WDS: wireless distribution interface
* @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
* @NL80211_IFTYPE_MESH_POINT: mesh point
* @NL80211_IFTYPE_P2P_CLIENT: P2P client
* @NL80211_IFTYPE_P2P_GO: P2P group owner
But what we really want to do is keep track of TSF sync and beaconing.
For beacon we have already given up on opmode and now use nbcnvifs.
Perhaps we could find some similar way to handle TSF sync?
/Björn
^ permalink raw reply
* [PATCH] ath9k_hw: fix carrier leakage calibration for AR9271
From: Rajkumar Manoharan @ 2011-01-14 20:12 UTC (permalink / raw)
To: linux-wireless; +Cc: Rajkumar Manoharan
AR9285 carrier leakage calibration related workaround on high
temperature is not applicable for AR9271.
Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/ar9002_calib.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index ea2e7d7..14d7d2a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -805,7 +805,10 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
- if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
+ if (AR_SREV_9271(ah)) {
+ if (!ar9285_hw_cl_cal(ah, chan))
+ return false;
+ } else if (AR_SREV_9285_12_OR_LATER(ah)) {
if (!ar9285_hw_clc(ah, chan))
return false;
} else {
--
1.7.3.5
^ permalink raw reply related
* Compat-wireless release for 2011-01-14 is baked
From: Compat-wireless cronjob account @ 2011-01-14 20:04 UTC (permalink / raw)
To: linux-wireless
>From git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next
8d4d54a..2271958 history -> origin/history
+ c698755...1d506f8 master -> origin/master (forced update)
f878133..581548d stable -> origin/stable
* [new tag] next-20110114 -> next-20110114
compat-wireless code metrics
782520 - Total upstream lines of code being pulled
2103 - backport code changes
1843 - backport code additions
260 - backport code deletions
7279 - backport from compat module
9382 - total backport code
1.1989 - % of code consists of backport work
1531 - Crap changes not yet posted
1488 - Crap additions not yet posted
43 - Crap deletions not yet posted
0.1956 - % of crap code
Base tree: linux-next.git
Base tree version: next-20110114
compat-wireless release: compat-wireless-2011-01-06-3-g8db1608-pc
^ permalink raw reply
* [PATCH] ath9k_htc: keep calibrated noise floor value for oper channel
From: Rajkumar Manoharan @ 2011-01-14 20:03 UTC (permalink / raw)
To: linux-wireless; +Cc: Rajkumar Manoharan
The ath9k_hw assumes that caldata is valid only for
oper channel. But with ath9k_htc case, the caldata is
passed for all channels on hw_reset though we are not doing
calibration on that channel. So the oper channel's nf history
got cleared to default due to mismatch in channel flags.
This patch also saves some space.
Signed-off-by: Rajkumar Manoharan <rmanoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/htc.h | 2 +-
drivers/net/wireless/ath/ath9k/htc_drv_main.c | 7 ++++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 1ce506f..c976600 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -366,7 +366,7 @@ struct ath9k_htc_priv {
u16 seq_no;
u32 bmiss_cnt;
- struct ath9k_hw_cal_data caldata[ATH9K_NUM_CHANNELS];
+ struct ath9k_hw_cal_data caldata;
spinlock_t beacon_lock;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index f4d576b..187af5b 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -121,7 +121,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
struct ath_hw *ah = priv->ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_channel *channel = priv->hw->conf.channel;
- struct ath9k_hw_cal_data *caldata;
+ struct ath9k_hw_cal_data *caldata = NULL;
enum htc_phymode mode;
__be16 htc_mode;
u8 cmd_rsp;
@@ -139,7 +139,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv)
WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
WMI_CMD(WMI_STOP_RECV_CMDID);
- caldata = &priv->caldata[channel->hw_value];
+ caldata = &priv->caldata;
ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
if (ret) {
ath_err(common,
@@ -202,7 +202,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
fastcc);
- caldata = &priv->caldata[channel->hw_value];
+ if (!fastcc)
+ caldata = &priv->caldata;
ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
if (ret) {
ath_err(common,
--
1.7.3.5
^ permalink raw reply related
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