Linux wireless drivers development
 help / color / mirror / Atom feed
* Re: [PATCH] b43: Fix locking problem when stopping rfkill polling
From: John W. Linville @ 2009-10-08 22:31 UTC (permalink / raw)
  To: Larry Finger; +Cc: linux-wireless, Greg Kroah-Hartman
In-Reply-To: <4ACE4A48.9070901@lwfinger.net>

On Thu, Oct 08, 2009 at 03:23:36PM -0500, Larry Finger wrote:
> On 10/07/2009 02:01 PM, John W. Linville wrote:
>> OK, but why do we start polling under the lock but stop polling without
>> the lock?  Should we start polling without holding the lock too?
>
> I see that this patch was committed. I hope that you will be sending it 
> upstream for 2.6.32. The correct version has been sent to stable for 
> inclusion in 2.6.31, but as usual, a mainline commit ID will be needed.

I've folded this into "b43: Fix PPC crash in rfkill polling on unload"
for sending upstream.

Thanks!

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* pull request: wireless-2.6 2009-10-08
From: John W. Linville @ 2009-10-08 22:34 UTC (permalink / raw)
  To: davem; +Cc: linux-wireless, netdev, linux-kernel

Dave,

Here is another batch of fixes intended for 2.6.32.  Most of them are
short, self-contained and more-or-less obvious.  Most of them have been
baking in -next for several days.

The b43 patch from Albert Herranz looks big, but most of it is moving a
structure definition within a header file.  It also changes some DMA
buffers from stack to heap allocation.

Please let me know if there are problems!

Thanks,

John

---

Individual patches are available here:

	http://www.kernel.org/pub/linux/kernel/people/linville/wireless-2.6/

---

The following changes since commit a4d63a943735efa30270ce70716d43323fd40f02:
  Thomas Chou (1):
        ethoc: limit the number of buffers to 128

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master

Albert Herranz (1):
      b43: do not stack-allocate pio rx/tx header and tail buffers

Bjorn Helgaas (1):
      iwlwifi: use %pM for formatted MAC addresses

Jay Sternberg (1):
      iwlwifi: incorrect method used for finding valid OTP blocks

Johannes Berg (2):
      mac80211: fix vlan and optimise RX
      cfg80211: fix netns error unwinding bug

Larry Finger (1):
      b43: Fix PPC crash in rfkill polling on unload

Michael Buesch (2):
      b43: Don't use struct wldev after detach.
      b43: Protect sanity check against physical device removal

Reinette Chatre (2):
      iwlwifi: fix compile warning
      iwlagn: fix compile warning in iwl5000_gain_computation

Roel Kluin (2):
      mac80211: fix ADM8211_SYNCTL_RFtype define
      mac80211: use kfree_skb() to free struct sk_buff pointers

Wey-Yi Guy (1):
      iwlwifi: fix EEPROM enhance tx power offset

 drivers/net/wireless/adm8211.h              |    2 +-
 drivers/net/wireless/b43/b43.h              |  168 +++++++++++++++------------
 drivers/net/wireless/b43/leds.c             |    4 +-
 drivers/net/wireless/b43/leds.h             |    4 +-
 drivers/net/wireless/b43/main.c             |    7 +-
 drivers/net/wireless/b43/pio.c              |   78 ++++++------
 drivers/net/wireless/b43/xmit.c             |    2 +-
 drivers/net/wireless/iwlwifi/iwl-3945-rs.c  |    2 +-
 drivers/net/wireless/iwlwifi/iwl-3945.c     |    2 +-
 drivers/net/wireless/iwlwifi/iwl-5000.c     |    2 +-
 drivers/net/wireless/iwlwifi/iwl-commands.h |    2 +-
 drivers/net/wireless/iwlwifi/iwl-eeprom.c   |   23 ++--
 drivers/net/wireless/iwlwifi/iwl-eeprom.h   |   20 ++--
 drivers/net/wireless/iwlwifi/iwl-rx.c       |    2 +-
 net/mac80211/rx.c                           |   10 ++-
 net/mac80211/sta_info.c                     |    2 +
 net/mac80211/tx.c                           |    3 +-
 net/mac80211/util.c                         |    4 +-
 net/wireless/nl80211.c                      |    3 +-
 19 files changed, 184 insertions(+), 156 deletions(-)

diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h
index 4f6ab13..b07e4d3 100644
--- a/drivers/net/wireless/adm8211.h
+++ b/drivers/net/wireless/adm8211.h
@@ -266,7 +266,7 @@ do {								\
 #define ADM8211_SYNCTL_CS1	(1 << 28)
 #define ADM8211_SYNCTL_CAL	(1 << 27)
 #define ADM8211_SYNCTL_SELCAL	(1 << 26)
-#define ADM8211_SYNCTL_RFtype	((1 << 24) || (1 << 23) || (1 << 22))
+#define ADM8211_SYNCTL_RFtype	((1 << 24) | (1 << 23) | (1 << 22))
 #define ADM8211_SYNCTL_RFMD	(1 << 22)
 #define ADM8211_SYNCTL_GENERAL	(0x7 << 22)
 /* SYNCTL 21:0 Data (Si4126: 18-bit data, 4-bit address) */
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index fa1549a..6607162 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -607,82 +607,7 @@ struct b43_qos_params {
 	struct ieee80211_tx_queue_params p;
 };
 
-struct b43_wldev;
-
-/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
-struct b43_wl {
-	/* Pointer to the active wireless device on this chip */
-	struct b43_wldev *current_dev;
-	/* Pointer to the ieee80211 hardware data structure */
-	struct ieee80211_hw *hw;
-
-	/* Global driver mutex. Every operation must run with this mutex locked. */
-	struct mutex mutex;
-	/* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ
-	 * handler, only. This basically is just the IRQ mask register. */
-	spinlock_t hardirq_lock;
-
-	/* The number of queues that were registered with the mac80211 subsystem
-	 * initially. This is a backup copy of hw->queues in case hw->queues has
-	 * to be dynamically lowered at runtime (Firmware does not support QoS).
-	 * hw->queues has to be restored to the original value before unregistering
-	 * from the mac80211 subsystem. */
-	u16 mac80211_initially_registered_queues;
-
-	/* We can only have one operating interface (802.11 core)
-	 * at a time. General information about this interface follows.
-	 */
-
-	struct ieee80211_vif *vif;
-	/* The MAC address of the operating interface. */
-	u8 mac_addr[ETH_ALEN];
-	/* Current BSSID */
-	u8 bssid[ETH_ALEN];
-	/* Interface type. (NL80211_IFTYPE_XXX) */
-	int if_type;
-	/* Is the card operating in AP, STA or IBSS mode? */
-	bool operating;
-	/* filter flags */
-	unsigned int filter_flags;
-	/* Stats about the wireless interface */
-	struct ieee80211_low_level_stats ieee_stats;
-
-#ifdef CONFIG_B43_HWRNG
-	struct hwrng rng;
-	bool rng_initialized;
-	char rng_name[30 + 1];
-#endif /* CONFIG_B43_HWRNG */
-
-	/* List of all wireless devices on this chip */
-	struct list_head devlist;
-	u8 nr_devs;
-
-	bool radiotap_enabled;
-	bool radio_enabled;
-
-	/* The beacon we are currently using (AP or IBSS mode). */
-	struct sk_buff *current_beacon;
-	bool beacon0_uploaded;
-	bool beacon1_uploaded;
-	bool beacon_templates_virgin; /* Never wrote the templates? */
-	struct work_struct beacon_update_trigger;
-
-	/* The current QOS parameters for the 4 queues. */
-	struct b43_qos_params qos_params[4];
-
-	/* Work for adjustment of the transmission power.
-	 * This is scheduled when we determine that the actual TX output
-	 * power doesn't match what we want. */
-	struct work_struct txpower_adjust_work;
-
-	/* Packet transmit work */
-	struct work_struct tx_work;
-	/* Queue of packets to be transmitted. */
-	struct sk_buff_head tx_queue;
-
-	/* The device LEDs. */
-	struct b43_leds leds;
-};
+struct b43_wl;
 
 /* The type of the firmware file. */
 enum b43_firmware_file_type {
@@ -824,6 +749,97 @@ struct b43_wldev {
 #endif
 };
 
+/*
+ * Include goes here to avoid a dependency problem.
+ * A better fix would be to integrate xmit.h into b43.h.
+ */
+#include "xmit.h"
+
+/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
+struct b43_wl {
+	/* Pointer to the active wireless device on this chip */
+	struct b43_wldev *current_dev;
+	/* Pointer to the ieee80211 hardware data structure */
+	struct ieee80211_hw *hw;
+
+	/* Global driver mutex. Every operation must run with this mutex locked. */
+	struct mutex mutex;
+	/* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ
+	 * handler, only. This basically is just the IRQ mask register. */
+	spinlock_t hardirq_lock;
+
+	/* The number of queues that were registered with the mac80211 subsystem
+	 * initially. This is a backup copy of hw->queues in case hw->queues has
+	 * to be dynamically lowered at runtime (Firmware does not support QoS).
+	 * hw->queues has to be restored to the original value before unregistering
+	 * from the mac80211 subsystem. */
+	u16 mac80211_initially_registered_queues;
+
+	/* We can only have one operating interface (802.11 core)
+	 * at a time. General information about this interface follows.
+	 */
+
+	struct ieee80211_vif *vif;
+	/* The MAC address of the operating interface. */
+	u8 mac_addr[ETH_ALEN];
+	/* Current BSSID */
+	u8 bssid[ETH_ALEN];
+	/* Interface type. (NL80211_IFTYPE_XXX) */
+	int if_type;
+	/* Is the card operating in AP, STA or IBSS mode? */
+	bool operating;
+	/* filter flags */
+	unsigned int filter_flags;
+	/* Stats about the wireless interface */
+	struct ieee80211_low_level_stats ieee_stats;
+
+#ifdef CONFIG_B43_HWRNG
+	struct hwrng rng;
+	bool rng_initialized;
+	char rng_name[30 + 1];
+#endif /* CONFIG_B43_HWRNG */
+
+	/* List of all wireless devices on this chip */
+	struct list_head devlist;
+	u8 nr_devs;
+
+	bool radiotap_enabled;
+	bool radio_enabled;
+
+	/* The beacon we are currently using (AP or IBSS mode). */
+	struct sk_buff *current_beacon;
+	bool beacon0_uploaded;
+	bool beacon1_uploaded;
+	bool beacon_templates_virgin; /* Never wrote the templates? */
+	struct work_struct beacon_update_trigger;
+
+	/* The current QOS parameters for the 4 queues. */
+	struct b43_qos_params qos_params[4];
+
+	/* Work for adjustment of the transmission power.
+	 * This is scheduled when we determine that the actual TX output
+	 * power doesn't match what we want. */
+	struct work_struct txpower_adjust_work;
+
+	/* Packet transmit work */
+	struct work_struct tx_work;
+	/* Queue of packets to be transmitted. */
+	struct sk_buff_head tx_queue;
+
+	/* The device LEDs. */
+	struct b43_leds leds;
+
+#ifdef CONFIG_B43_PIO
+	/*
+	 * RX/TX header/tail buffers used by the frame transmit functions.
+	 */
+	struct b43_rxhdr_fw4 rxhdr;
+	struct b43_txhdr txhdr;
+	u8 rx_tail[4];
+	u8 tx_tail[4];
+#endif /* CONFIG_B43_PIO */
+};
+
 static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
 {
 	return hw->priv;
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index fbe3d4f..1e8dba4 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -348,9 +348,9 @@ void b43_leds_register(struct b43_wldev *dev)
 	}
 }
 
-void b43_leds_unregister(struct b43_wldev *dev)
+void b43_leds_unregister(struct b43_wl *wl)
 {
-	struct b43_leds *leds = &dev->wl->leds;
+	struct b43_leds *leds = &wl->leds;
 
 	b43_unregister_led(&leds->led_tx);
 	b43_unregister_led(&leds->led_rx);
diff --git a/drivers/net/wireless/b43/leds.h b/drivers/net/wireless/b43/leds.h
index 9592e4c..4c56187 100644
--- a/drivers/net/wireless/b43/leds.h
+++ b/drivers/net/wireless/b43/leds.h
@@ -60,7 +60,7 @@ enum b43_led_behaviour {
 };
 
 void b43_leds_register(struct b43_wldev *dev);
-void b43_leds_unregister(struct b43_wldev *dev);
+void b43_leds_unregister(struct b43_wl *wl);
 void b43_leds_init(struct b43_wldev *dev);
 void b43_leds_exit(struct b43_wldev *dev);
 void b43_leds_stop(struct b43_wldev *dev);
@@ -76,7 +76,7 @@ struct b43_leds {
 static inline void b43_leds_register(struct b43_wldev *dev)
 {
 }
-static inline void b43_leds_unregister(struct b43_wldev *dev)
+static inline void b43_leds_unregister(struct b43_wl *wl)
 {
 }
 static inline void b43_leds_init(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 9b907a3..df6b26a 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3874,6 +3874,7 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev)
 {
 	struct b43_wl *wl = dev->wl;
 	struct b43_wldev *orig_dev;
+	u32 mask;
 
 redo:
 	if (!dev || b43_status(dev) < B43_STAT_STARTED)
@@ -3920,7 +3921,8 @@ redo:
 			goto redo;
 		return dev;
 	}
-	B43_WARN_ON(b43_read32(dev, B43_MMIO_GEN_IRQ_MASK));
+	mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
+	B43_WARN_ON(mask != 0xFFFFFFFF && mask);
 
 	/* Drain the TX queue */
 	while (skb_queue_len(&wl->tx_queue))
@@ -4499,6 +4501,7 @@ static void b43_op_stop(struct ieee80211_hw *hw)
 
 	cancel_work_sync(&(wl->beacon_update_trigger));
 
+	wiphy_rfkill_stop_polling(hw->wiphy);
 	mutex_lock(&wl->mutex);
 	if (b43_status(dev) >= B43_STAT_STARTED) {
 		dev = b43_wireless_core_stop(dev);
@@ -4997,7 +5000,7 @@ static void b43_remove(struct ssb_device *dev)
 
 	if (list_empty(&wl->devlist)) {
 		b43_rng_exit(wl);
-		b43_leds_unregister(wldev);
+		b43_leds_unregister(wl);
 		/* Last core on the chip unregistered.
 		 * We can destroy common struct b43_wl.
 		 */
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 9c13979..dbbf0d1 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -331,6 +331,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
 				unsigned int data_len)
 {
 	struct b43_wldev *dev = q->dev;
+	struct b43_wl *wl = dev->wl;
 	const u8 *data = _data;
 
 	ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
@@ -340,13 +341,12 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
 			q->mmio_base + B43_PIO_TXDATA,
 			sizeof(u16));
 	if (data_len & 1) {
-		u8 tail[2] = { 0, };
-
 		/* Write the last byte. */
 		ctl &= ~B43_PIO_TXCTL_WRITEHI;
 		b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
-		tail[0] = data[data_len - 1];
-		ssb_block_write(dev->dev, tail, 2,
+		wl->tx_tail[0] = data[data_len - 1];
+		wl->tx_tail[1] = 0;
+		ssb_block_write(dev->dev, wl->tx_tail, 2,
 				q->mmio_base + B43_PIO_TXDATA,
 				sizeof(u16));
 	}
@@ -381,6 +381,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
 				unsigned int data_len)
 {
 	struct b43_wldev *dev = q->dev;
+	struct b43_wl *wl = dev->wl;
 	const u8 *data = _data;
 
 	ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
@@ -391,29 +392,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
 			q->mmio_base + B43_PIO8_TXDATA,
 			sizeof(u32));
 	if (data_len & 3) {
-		u8 tail[4] = { 0, };
-
+		wl->tx_tail[3] = 0;
 		/* Write the last few bytes. */
 		ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
 			 B43_PIO8_TXCTL_24_31);
 		switch (data_len & 3) {
 		case 3:
 			ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
-			tail[0] = data[data_len - 3];
-			tail[1] = data[data_len - 2];
-			tail[2] = data[data_len - 1];
+			wl->tx_tail[0] = data[data_len - 3];
+			wl->tx_tail[1] = data[data_len - 2];
+			wl->tx_tail[2] = data[data_len - 1];
 			break;
 		case 2:
 			ctl |= B43_PIO8_TXCTL_8_15;
-			tail[0] = data[data_len - 2];
-			tail[1] = data[data_len - 1];
+			wl->tx_tail[0] = data[data_len - 2];
+			wl->tx_tail[1] = data[data_len - 1];
+			wl->tx_tail[2] = 0;
 			break;
 		case 1:
-			tail[0] = data[data_len - 1];
+			wl->tx_tail[0] = data[data_len - 1];
+			wl->tx_tail[1] = 0;
+			wl->tx_tail[2] = 0;
 			break;
 		}
 		b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
-		ssb_block_write(dev->dev, tail, 4,
+		ssb_block_write(dev->dev, wl->tx_tail, 4,
 				q->mmio_base + B43_PIO8_TXDATA,
 				sizeof(u32));
 	}
@@ -445,8 +448,9 @@ static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
 static int pio_tx_frame(struct b43_pio_txqueue *q,
 			struct sk_buff *skb)
 {
+	struct b43_wldev *dev = q->dev;
+	struct b43_wl *wl = dev->wl;
 	struct b43_pio_txpacket *pack;
-	struct b43_txhdr txhdr;
 	u16 cookie;
 	int err;
 	unsigned int hdrlen;
@@ -457,8 +461,8 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
 			  struct b43_pio_txpacket, list);
 
 	cookie = generate_cookie(q, pack);
-	hdrlen = b43_txhdr_size(q->dev);
-	err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb,
+	hdrlen = b43_txhdr_size(dev);
+	err = b43_generate_txhdr(dev, (u8 *)&wl->txhdr, skb,
 				 info, cookie);
 	if (err)
 		return err;
@@ -466,15 +470,15 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
 	if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
 		/* Tell the firmware about the cookie of the last
 		 * mcast frame, so it can clear the more-data bit in it. */
-		b43_shm_write16(q->dev, B43_SHM_SHARED,
+		b43_shm_write16(dev, B43_SHM_SHARED,
 				B43_SHM_SH_MCASTCOOKIE, cookie);
 	}
 
 	pack->skb = skb;
 	if (q->rev >= 8)
-		pio_tx_frame_4byte_queue(pack, (const u8 *)&txhdr, hdrlen);
+		pio_tx_frame_4byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
 	else
-		pio_tx_frame_2byte_queue(pack, (const u8 *)&txhdr, hdrlen);
+		pio_tx_frame_2byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
 
 	/* Remove it from the list of available packet slots.
 	 * It will be put back when we receive the status report. */
@@ -614,14 +618,14 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev,
 static bool pio_rx_frame(struct b43_pio_rxqueue *q)
 {
 	struct b43_wldev *dev = q->dev;
-	struct b43_rxhdr_fw4 rxhdr;
+	struct b43_wl *wl = dev->wl;
 	u16 len;
 	u32 macstat;
 	unsigned int i, padding;
 	struct sk_buff *skb;
 	const char *err_msg = NULL;
 
-	memset(&rxhdr, 0, sizeof(rxhdr));
+	memset(&wl->rxhdr, 0, sizeof(wl->rxhdr));
 
 	/* Check if we have data and wait for it to get ready. */
 	if (q->rev >= 8) {
@@ -659,16 +663,16 @@ data_ready:
 
 	/* Get the preamble (RX header) */
 	if (q->rev >= 8) {
-		ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
+		ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
 			       q->mmio_base + B43_PIO8_RXDATA,
 			       sizeof(u32));
 	} else {
-		ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr),
+		ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
 			       q->mmio_base + B43_PIO_RXDATA,
 			       sizeof(u16));
 	}
 	/* Sanity checks. */
-	len = le16_to_cpu(rxhdr.frame_len);
+	len = le16_to_cpu(wl->rxhdr.frame_len);
 	if (unlikely(len > 0x700)) {
 		err_msg = "len > 0x700";
 		goto rx_error;
@@ -678,7 +682,7 @@ data_ready:
 		goto rx_error;
 	}
 
-	macstat = le32_to_cpu(rxhdr.mac_status);
+	macstat = le32_to_cpu(wl->rxhdr.mac_status);
 	if (macstat & B43_RX_MAC_FCSERR) {
 		if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
 			/* Drop frames with failed FCS. */
@@ -703,24 +707,22 @@ data_ready:
 			       q->mmio_base + B43_PIO8_RXDATA,
 			       sizeof(u32));
 		if (len & 3) {
-			u8 tail[4] = { 0, };
-
 			/* Read the last few bytes. */
-			ssb_block_read(dev->dev, tail, 4,
+			ssb_block_read(dev->dev, wl->rx_tail, 4,
 				       q->mmio_base + B43_PIO8_RXDATA,
 				       sizeof(u32));
 			switch (len & 3) {
 			case 3:
-				skb->data[len + padding - 3] = tail[0];
-				skb->data[len + padding - 2] = tail[1];
-				skb->data[len + padding - 1] = tail[2];
+				skb->data[len + padding - 3] = wl->rx_tail[0];
+				skb->data[len + padding - 2] = wl->rx_tail[1];
+				skb->data[len + padding - 1] = wl->rx_tail[2];
 				break;
 			case 2:
-				skb->data[len + padding - 2] = tail[0];
-				skb->data[len + padding - 1] = tail[1];
+				skb->data[len + padding - 2] = wl->rx_tail[0];
+				skb->data[len + padding - 1] = wl->rx_tail[1];
 				break;
 			case 1:
-				skb->data[len + padding - 1] = tail[0];
+				skb->data[len + padding - 1] = wl->rx_tail[0];
 				break;
 			}
 		}
@@ -729,17 +731,15 @@ data_ready:
 			       q->mmio_base + B43_PIO_RXDATA,
 			       sizeof(u16));
 		if (len & 1) {
-			u8 tail[2] = { 0, };
-
 			/* Read the last byte. */
-			ssb_block_read(dev->dev, tail, 2,
+			ssb_block_read(dev->dev, wl->rx_tail, 2,
 				       q->mmio_base + B43_PIO_RXDATA,
 				       sizeof(u16));
-			skb->data[len + padding - 1] = tail[0];
+			skb->data[len + padding - 1] = wl->rx_tail[0];
 		}
 	}
 
-	b43_rx(q->dev, skb, &rxhdr);
+	b43_rx(q->dev, skb, &wl->rxhdr);
 
 	return 1;
 
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index ac9f600..892573b 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -27,7 +27,7 @@
 
 */
 
-#include "xmit.h"
+#include "b43.h"
 #include "phy_common.h"
 #include "dma.h"
 #include "pio.h"
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index a16bd41..cbb0585 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -702,7 +702,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
 		u8 sta_id = iwl_find_station(priv, hdr->addr1);
 
 		if (sta_id == IWL_INVALID_STATION) {
-			IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n",
+			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
 				       hdr->addr1);
 			sta_id = iwl_add_station(priv, hdr->addr1, false,
 				CMD_ASYNC, NULL);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index e70c5b0..231c833 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -610,7 +610,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
 	if (rx_status.band == IEEE80211_BAND_5GHZ)
 		rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
 
-	rx_status.antenna = le16_to_cpu(rx_hdr->phy_flags &
+	rx_status.antenna = (le16_to_cpu(rx_hdr->phy_flags) &
 					RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
 
 	/* set the preamble flag if appropriate */
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index eb08f44..524e7e4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -317,7 +317,7 @@ static void iwl5000_gain_computation(struct iwl_priv *priv,
 			(s32)average_noise[i])) / 1500;
 		/* bound gain by 2 bits value max, 3rd bit is sign */
 		data->delta_gain_code[i] =
-			min(abs(delta_g), CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
+			min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
 
 		if (delta_g < 0)
 			/* set negative sign */
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 2c5c88f..4afaf77 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1154,7 +1154,7 @@ struct iwl_wep_cmd {
 #define RX_RES_PHY_FLAGS_MOD_CCK_MSK		cpu_to_le16(1 << 1)
 #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	cpu_to_le16(1 << 2)
 #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK	cpu_to_le16(1 << 3)
-#define RX_RES_PHY_FLAGS_ANTENNA_MSK		cpu_to_le16(0xf0)
+#define RX_RES_PHY_FLAGS_ANTENNA_MSK		0xf0
 #define RX_RES_PHY_FLAGS_ANTENNA_POS		4
 
 #define RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 3d2b93a..e14c995 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -410,7 +410,6 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
 					u16 *validblockaddr)
 {
 	u16 next_link_addr = 0, link_value = 0, valid_addr;
-	int ret = 0;
 	int usedblocks = 0;
 
 	/* set addressing mode to absolute to traverse the link list */
@@ -430,29 +429,29 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
 		 * check for more block on the link list
 		 */
 		valid_addr = next_link_addr;
-		next_link_addr = link_value;
+		next_link_addr = link_value * sizeof(u16);
 		IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
 			       usedblocks, next_link_addr);
 		if (iwl_read_otp_word(priv, next_link_addr, &link_value))
 			return -EINVAL;
 		if (!link_value) {
 			/*
-			 * reach the end of link list,
+			 * reach the end of link list, return success and
 			 * set address point to the starting address
 			 * of the image
 			 */
-			goto done;
+			*validblockaddr = valid_addr;
+			/* skip first 2 bytes (link list pointer) */
+			*validblockaddr += 2;
+			return 0;
 		}
 		/* more in the link list, continue */
 		usedblocks++;
-	} while (usedblocks < priv->cfg->max_ll_items);
-	/* OTP full, use last block */
-	IWL_DEBUG_INFO(priv, "OTP is full, use last block\n");
-done:
-	*validblockaddr = valid_addr;
-	/* skip first 2 bytes (link list pointer) */
-	*validblockaddr += 2;
-	return ret;
+	} while (usedblocks <= priv->cfg->max_ll_items);
+
+	/* OTP has no valid blocks */
+	IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n");
+	return -EINVAL;
 }
 
 /**
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 6b68db7..80b9e45 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -220,35 +220,35 @@ struct iwl_eeprom_enhanced_txpwr {
  * Section 10: 2.4 GHz 40MHz channels: 132, 44 (_above_)
  */
 /* 2.4 GHz band: CCK */
-#define EEPROM_LB_CCK_20_COMMON       ((0xAA)\
+#define EEPROM_LB_CCK_20_COMMON       ((0xA8)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 8 bytes */
 /* 2.4 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
-#define EEPROM_LB_OFDM_COMMON       ((0xB2)\
+#define EEPROM_LB_OFDM_COMMON       ((0xB0)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */
 /* 5.2 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
-#define EEPROM_HB_OFDM_COMMON       ((0xCA)\
+#define EEPROM_HB_OFDM_COMMON       ((0xC8)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */
 /* 2.4GHz band channels:
  *	1Legacy, 1HT, 2Legacy, 2HT, 10Legacy, 10HT, 11Legacy, 11HT */
-#define EEPROM_LB_OFDM_20_BAND       ((0xE2)\
+#define EEPROM_LB_OFDM_20_BAND       ((0xE0)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 64 bytes */
 /* 2.4 GHz band HT40 channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) */
-#define EEPROM_LB_OFDM_HT40_BAND       ((0x122)\
+#define EEPROM_LB_OFDM_HT40_BAND       ((0x120)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 40 bytes */
 /* 5.2GHz band channels: 36Legacy, 36HT, 64Legacy, 64HT, 100Legacy, 100HT */
-#define EEPROM_HB_OFDM_20_BAND       ((0x14A)\
+#define EEPROM_HB_OFDM_20_BAND       ((0x148)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 48 bytes */
 /* 5.2 GHz band HT40 channels: (36,+1) (60,+1) (100,+1) */
-#define EEPROM_HB_OFDM_HT40_BAND       ((0x17A)\
+#define EEPROM_HB_OFDM_HT40_BAND       ((0x178)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 24 bytes */
 /* 2.4 GHz band, channnel 13: Legacy, HT */
-#define EEPROM_LB_OFDM_20_CHANNEL_13       ((0x192)\
+#define EEPROM_LB_OFDM_20_CHANNEL_13       ((0x190)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 16 bytes */
 /* 5.2 GHz band, channnel 140: Legacy, HT */
-#define EEPROM_HB_OFDM_20_CHANNEL_140       ((0x1A2)\
+#define EEPROM_HB_OFDM_20_CHANNEL_140       ((0x1A0)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 16 bytes */
 /* 5.2 GHz band, HT40 channnels (132,+1) (44,+1) */
-#define EEPROM_HB_OFDM_HT40_BAND_1       ((0x1B2)\
+#define EEPROM_HB_OFDM_HT40_BAND_1       ((0x1B0)\
 		| INDIRECT_ADDRESS | INDIRECT_REGULATORY)   /* 16 bytes */
 
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 8e1bb53..493626b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -1044,7 +1044,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
 	 * as a bitmask.
 	 */
 	rx_status.antenna =
-		le16_to_cpu(phy_res->phy_flags & RX_RES_PHY_FLAGS_ANTENNA_MSK)
+		(le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
 		>> RX_RES_PHY_FLAGS_ANTENNA_POS;
 
 	/* set the preamble flag if appropriate */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c01588f..865fbc0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2164,11 +2164,17 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
 	skb = rx.skb;
 
-	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+	if (rx.sdata && ieee80211_is_data(hdr->frame_control)) {
+		rx.flags |= IEEE80211_RX_RA_MATCH;
+		prepares = prepare_for_handlers(rx.sdata, &rx, hdr);
+		if (prepares)
+			prev = rx.sdata;
+	} else list_for_each_entry_rcu(sdata, &local->interfaces, list) {
 		if (!netif_running(sdata->dev))
 			continue;
 
-		if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+		if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+		    sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 			continue;
 
 		rx.flags |= IEEE80211_RX_RA_MATCH;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index eec0014..594f231 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -361,6 +361,7 @@ int sta_info_insert(struct sta_info *sta)
 					     u.ap);
 
 		drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, &sta->sta);
+		sdata = sta->sdata;
 	}
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -496,6 +497,7 @@ static void __sta_info_unlink(struct sta_info **sta)
 
 		drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
 			       &(*sta)->sta);
+		sdata = (*sta)->sdata;
 	}
 
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index fd40282..db4bda6 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1704,7 +1704,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 	if (!is_multicast_ether_addr(hdr.addr1)) {
 		rcu_read_lock();
 		sta = sta_info_get(local, hdr.addr1);
-		if (sta)
+		/* XXX: in the future, use sdata to look up the sta */
+		if (sta && sta->sdata == sdata)
 			sta_flags = get_sta_flags(sta);
 		rcu_read_unlock();
 	}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index dd65643..aeb65b3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -339,7 +339,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 	if (WARN_ON(!info->control.vif)) {
-		kfree(skb);
+		kfree_skb(skb);
 		return;
 	}
 
@@ -367,7 +367,7 @@ int ieee80211_add_pending_skbs(struct ieee80211_local *local,
 		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
 		if (WARN_ON(!info->control.vif)) {
-			kfree(skb);
+			kfree_skb(skb);
 			continue;
 		}
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index eddab09..ca3c92a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4029,7 +4029,7 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
 	rdev = cfg80211_get_dev_from_info(info);
 	if (IS_ERR(rdev)) {
 		err = PTR_ERR(rdev);
-		goto out;
+		goto out_rtnl;
 	}
 
 	net = get_net_ns_by_pid(pid);
@@ -4049,6 +4049,7 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
 	put_net(net);
  out:
 	cfg80211_unlock_rdev(rdev);
+ out_rtnl:
 	rtnl_unlock();
 	return err;
 }
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply related

* WARNING: at net/mac80211/agg-tx.c:145 ___ieee80211_stop_tx_ba_session+0x91/0xa0 [mac80211]
From: Thomas Backlund @ 2009-10-08 21:01 UTC (permalink / raw)
  To: Linux Kernel Mailing List; +Cc: linux-wireless@vger.kernel.org


I hit this today:

kernel is a 2.6.31.3 based one built for x86_64

the wireless is connected to a WPA2 encrypted network

Wireless card is:
04:00.0 Network controller [0280]: Intel Corporation PRO/Wireless 4965 
AG or AGN [Kedron] Network Connection [8086:4229] (rev 61)

ucode is 228.61.2.24


> [  108.478772] iwlagn 0000:04:00.0: iwl_tx_agg_start on ra = 00:24:01:38:cb:48 tid = 0
> [  108.478979] iwlagn 0000:04:00.0: Microcode HW error detected.  Restarting.
> [  108.706591] Registered led device: iwl-phy0::radio
> [  108.706607] Registered led device: iwl-phy0::assoc
> [  108.706620] Registered led device: iwl-phy0::RX
> [  108.706632] Registered led device: iwl-phy0::TX
> [  109.479039] iwlagn 0000:04:00.0: Stopping AGG while state not IWL_AGG_ON
> [  109.479045] iwlagn 0000:04:00.0: queue number out of range: 0, must be 7 to 14
> [  109.479046] ------------[ cut here ]------------
> [  109.479066] WARNING: at net/mac80211/agg-tx.c:145 ___ieee80211_stop_tx_ba_session+0x91/0xa0 [mac80211]()
> [  109.479068] Hardware name: TravelMate 5720                
> [  109.479070] Modules linked in: cryptd aes_x86_64 aes_generic af_packet ipv6 binfmt_misc loop fuse dm_mirror dm_region_hash dm_log dm_mod cpufreq_ondemand cpufreq_conservative cpufreq_powersave acpi_cpufreq freq_table tifm_sd mmc_block tifm_7xx1 tifm_core nvram radeon ttm drm_kms_helper drm i2c_algo_bit btusb bluetooth arc4 ecb snd_hda_codec_realtek snd_hda_intel snd_hda_codec iwlagn pcmcia iwlcore mac80211 snd_hwdep snd_seq_dummy firewire_ohci snd_seq_oss firewire_core snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss cfg80211 snd_pcm crc_itu_t nsc_ircc uvcvideo videodev v4l1_compat v4l2_compat_ioctl32 iTCO_wdt yenta_socket rsrc_nonstatic acer_wmi irda tg3 rfkill ohci1394 ieee1394 snd_timer snd_mixer_oss libphy crc_ccitt snd i2c_i801 joydev serio_raw pcspkr sdhci_pci i2c_core iTCO_vendor_support soundcore evdev sdhci pcmcia_core mmc_core snd_page_alloc led_class rtc_cmos wmi battery container button ac video processor thermal sr_mod output sg ata_piix ahci libata sd_
mod scsi_mod crc_t10dif ext4 jbd2 crc16 uhci_hcd ohci_hcd ehci_hcd usbhid hid usbcore [last unloaded: scsi_wait_scan]
> [  109.479141] Pid: 0, comm: swapper Not tainted 2.6.31.3-tmb-desktop-1mdv #1
> [  109.479143] Call Trace:
> [  109.479145]  <IRQ>  [<ffffffff81043a88>] warn_slowpath_common+0x78/0xb0
> [  109.479154]  [<ffffffff81043acf>] warn_slowpath_null+0xf/0x20
> [  109.479161]  [<ffffffffa0361081>] ___ieee80211_stop_tx_ba_session+0x91/0xa0 [mac80211]
> [  109.479169]  [<ffffffffa0361286>] sta_addba_resp_timer_expired+0x56/0x90 [mac80211]
> [  109.479177]  [<ffffffffa0361230>] ? sta_addba_resp_timer_expired+0x0/0x90 [mac80211]
> [  109.479181]  [<ffffffff8104e3fb>] run_timer_softirq+0x15b/0x250
> [  109.479183]  [<ffffffff810493bf>] __do_softirq+0xaf/0x140
> [  109.479187]  [<ffffffff8100fa2a>] ? timer_interrupt+0x1a/0x30
> [  109.479190]  [<ffffffff8100d06c>] call_softirq+0x1c/0x30
> [  109.479192]  [<ffffffff8100f075>] do_softirq+0x45/0x80
> [  109.479194]  [<ffffffff81049805>] irq_exit+0x95/0xa0
> [  109.479196]  [<ffffffff8100e600>] do_IRQ+0x70/0xe0
> [  109.479199]  [<ffffffff8100c8d3>] ret_from_intr+0x0/0xa
> [  109.479201]  <EOI>  [<ffffffffa016cd25>] ? acpi_idle_enter_bm+0x26c/0x297 [processor]
> [  109.479215]  [<ffffffffa016cd1b>] ? acpi_idle_enter_bm+0x262/0x297 [processor]
> [  109.479219]  [<ffffffff812406eb>] ? cpuidle_idle_call+0x9b/0x100
> [  109.479221]  [<ffffffff8100aa32>] ? cpu_idle+0x62/0xd0
> [  109.479225]  [<ffffffff812db9a1>] ? rest_init+0x81/0x90
> [  109.479229]  [<ffffffff814c01af>] ? start_kernel+0x356/0x362
> [  109.479232]  [<ffffffff814bf808>] ? x86_64_start_reservations+0x125/0x129
> [  109.479234]  [<ffffffff814bf8ed>] ? x86_64_start_kernel+0xe1/0xe8
> [  109.479236] ---[ end trace d34a38827329a2d4 ]---


--
Thomas


^ permalink raw reply

* Re: [.32-rc3] scheduler: iwlagn consistently high in "waiting for CPU"
From: Frans Pop @ 2009-10-08 20:59 UTC (permalink / raw)
  To: Mike Galbraith
  Cc: Arjan van de Ven, Linux Kernel Mailing List, Ingo Molnar,
	Peter Zijlstra, linux-wireless
In-Reply-To: <1255026217.6643.12.camel@marge.simson.net>

On Thursday 08 October 2009, Mike Galbraith wrote:
> I still see very high latencies coming out of idle (last noted was >
> 300ms, NO_HZ) with this patch,
>
> Like this:
>
> Cause                                           Maximum    Percentage
> Scheduler: waiting for cpu                   604.2 msec        49.0 %

I'm not seeing anything even remotely like that.

I've tried quieting the system down as much as possible, but that made
no difference. I do have NO_HZ set; will send my full config privately.

If you'd still like me to try your patch I will, but I'm not sure if
that has much value.

Cheers,
FJP

^ permalink raw reply

* [PATCH] libertas: remove double assignment of dev->netdev_ops
From: Luis R. Rodriguez @ 2009-10-08 20:46 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Luis R. Rodriguez, Holger Schurig

This came in through the patch titled:
    libertas: first stab at cfg80211 support

I only noticed it because it breaks compat-wireless :)

Cc: Holger Schurig <hs4233@mail.mn-solutions.de>
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
---
 drivers/net/wireless/libertas/main.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index e6da1df..87bfd17 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1276,7 +1276,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
 		goto err_adapter;
 	}
 
-	dev->netdev_ops = &lbs_netdev_ops;
 	dev->ieee80211_ptr = wdev;
 	dev->ml_priv = priv;
 	SET_NETDEV_DEV(dev, dmdev);
-- 
1.6.0.4


^ permalink raw reply related

* Re: [.32-rc3] scheduler: iwlagn consistently high in "waiting for CPU"
From: Markus Trippelsdorf @ 2009-10-08 20:34 UTC (permalink / raw)
  To: Mike Galbraith
  Cc: Frans Pop, Arjan van de Ven, Linux Kernel Mailing List,
	Ingo Molnar, Peter Zijlstra, linux-wireless
In-Reply-To: <1255026217.6643.12.camel@marge.simson.net>

On Thu, Oct 08, 2009 at 08:23:37PM +0200, Mike Galbraith wrote:
> On Thu, 2009-10-08 at 16:55 +0200, Frans Pop wrote:
> > On Thursday 08 October 2009, Arjan van de Ven wrote:
> > > From: Arjan van de Ven <arjan@linux.intel.com>
> > > Date: Thu, 24 Sep 2009 13:24:16 +0200
> > > Subject: [PATCH] x86, timers: check for pending timers after (device)
> > > interrupts
> > >
> > > Now that range timers and deferred timers are common, I found a
> > > problem with these using the "perf timechart" tool.
> > >
> > > It turns out that on x86, these two 'opportunistic' timers only
> > > get checked when another "real" timer happens.
> > > These opportunistic timers have the objective to save power by
> > > hitchhiking on other wakeups, as to avoid CPU wakeups by themselves
> > > as much as possible.
> > 
> > This patch makes quite a difference for me. iwlagn and phy0 now 
> > consistently show at ~10 ms or lower.
> > 
> > I do still get occasional high latencies, but those are for things like
> > "[rpc_wait_bit_killable]" or "Writing a page to disk", where I guess you'd 
> > expect them. Those high latencies are mostly only listed for "Global" and 
> > don't translate to individual processes.
> 
> I still see very high latencies coming out of idle (last noted was >
> 300ms, NO_HZ) with this patch, and wonder if the hunk below makes any
> difference whatsoever for you.  Here, it definitely does. (shouldn't)

I'm also seeing these strange, very high latencies here. Your patch
didn't help unfortunately.

This is from an otherwise idle NO_NZ system:

# ./perf sched latency

 -----------------------------------------------------------------------------------------
  Task                  |   Runtime ms  | Switches | Average delay ms | Maximum delay ms |
 -----------------------------------------------------------------------------------------
  ksoftirqd/0:4         |      2.216 ms |      170 | avg:   24.235 ms | max:  808.356 ms |
  ksoftirqd/1:6         |      2.611 ms |      205 | avg:    4.334 ms | max:  165.553 ms |
  migration/2:7         |      0.000 ms |        1 | avg:    3.060 ms | max:    3.060 ms |

With latencytop the ksoftirqd latency is over 1 sec frequently. (Could be
ondemand CPUfreq governor related?)

-- 
Markus

^ permalink raw reply

* Re: [PATCH] b43: Fix locking problem when stopping rfkill polling
From: Larry Finger @ 2009-10-08 20:23 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Greg Kroah-Hartman
In-Reply-To: <20091007190106.GB22394@tuxdriver.com>

On 10/07/2009 02:01 PM, John W. Linville wrote:
> OK, but why do we start polling under the lock but stop polling without
> the lock?  Should we start polling without holding the lock too?

I see that this patch was committed. I hope that you will be sending 
it upstream for 2.6.32. The correct version has been sent to stable 
for inclusion in 2.6.31, but as usual, a mainline commit ID will be 
needed.

Larry

^ permalink raw reply

* Re: [PATCH 15/20] wl1271: Multicast filtering configuration
From: Luciano Coelho @ 2009-10-08 20:15 UTC (permalink / raw)
  To: ext Johannes Berg
  Cc: linville@tuxdriver.com, linux-wireless@vger.kernel.org,
	Oikarinen Juuso (Nokia-D/Tampere)
In-Reply-To: <1255032103.3713.33.camel@johannes.local>

Hi Johannes,

ext Johannes Berg wrote:
> On Thu, 2009-10-08 at 21:56 +0300, Luciano Coelho wrote:
> 
>> +	/* first, get the filter parameters */
>> +	spin_lock_irqsave(&wl->wl_lock, flags);
>> +	fp = wl->filter_params;
>> +	wl->filter_params = NULL;
>> +	spin_unlock_irqrestore(&wl->wl_lock, flags);
>> +
>> +	if (!fp)
>> +		return;
> 
>> +	kfree(fp);
> 
>> +static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
>> +				       struct dev_addr_list *mc_list)
>> +{
>> +	struct wl1271 *wl = hw->priv;
>> +	struct wl1271_filter_params *fp;
>> +	unsigned long flags;
>> +	int i;
>> +
>> +	/*
>> +	 * FIXME: we should return a hash that will be passed to
>> +	 * configure_filter() instead of saving everything in the context.
>> +	 */
>> +
>> +	fp = kzalloc(sizeof(*fp), GFP_KERNEL);
>> +	if (!fp) {
>> +		wl1271_error("Out of memory setting filters.");
>> +		return 0;
>> +	}
> 
> It's a u64 on purpose, you can return the parameters struct to pass it
> through to configure_filter.

Yes, you're right.  It's just that I have forwarded-ported loads of patches at 
once, so I just made a quick hack to get this to compile and work before the 
real thing is done.  Juuso Oikarinen (who is also working on the wl1271) has 
already implemented the final solution for this and his patch will be included 
in one of my next batches ;)

Thanks a lot for your timely comment (as usual).

--
Cheers,
Luca.

^ permalink raw reply

* Re: [PATCH 15/20] wl1271: Multicast filtering configuration
From: Johannes Berg @ 2009-10-08 20:01 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linville, linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-16-git-send-email-luciano.coelho@nokia.com>

[-- Attachment #1: Type: text/plain, Size: 971 bytes --]

On Thu, 2009-10-08 at 21:56 +0300, Luciano Coelho wrote:

> +	/* first, get the filter parameters */
> +	spin_lock_irqsave(&wl->wl_lock, flags);
> +	fp = wl->filter_params;
> +	wl->filter_params = NULL;
> +	spin_unlock_irqrestore(&wl->wl_lock, flags);
> +
> +	if (!fp)
> +		return;

> +	kfree(fp);

> +static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
> +				       struct dev_addr_list *mc_list)
> +{
> +	struct wl1271 *wl = hw->priv;
> +	struct wl1271_filter_params *fp;
> +	unsigned long flags;
> +	int i;
> +
> +	/*
> +	 * FIXME: we should return a hash that will be passed to
> +	 * configure_filter() instead of saving everything in the context.
> +	 */
> +
> +	fp = kzalloc(sizeof(*fp), GFP_KERNEL);
> +	if (!fp) {
> +		wl1271_error("Out of memory setting filters.");
> +		return 0;
> +	}

It's a u64 on purpose, you can return the parameters struct to pass it
through to configure_filter.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply

* Re: [PATCH 7/7] ath5k: enable Power-Save Polls by setting the association ID
From: Luis R. Rodriguez @ 2009-10-08 19:51 UTC (permalink / raw)
  To: Bob Copeland; +Cc: linville, linux-wireless
In-Reply-To: <b6c5339f0910081126h3fe2dd25x9198dedf09a20cea@mail.gmail.com>

On Thu, Oct 8, 2009 at 2:26 PM, Bob Copeland <me@bobcopeland.com> wrote:
> On Tue, Oct 6, 2009 at 8:44 PM, Luis R. Rodriguez
> <lrodriguez@atheros.com> wrote:
>> @@ -3226,6 +3225,14 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
>>                        set_beacon_filter(hw, sc->assoc);
>>                ath5k_hw_set_ledstate(sc->ah, sc->assoc ?
>>                        AR5K_LED_ASSOC : AR5K_LED_INIT);
>> +               if (bss_conf->assoc) {
>> +                       ATH5K_DBG(sc, ATH5K_DEBUG_ANY,
>> +                                 "Bss Info ASSOC %d, bssid: %pM\n",
>> +                                 bss_conf->aid, common->curbssid);
>> +                       common->curaid = bss_conf->aid;
>> +                       ath5k_hw_set_associd(ah);
>> +                       /* Once ANI is available you would start it here */
>> +               }
>
> Just quick question - do we only want to call this if we are associated?
>
> Or maybe we should call it to reset the mask if we are unassociated...
>
> I wrote a patch a while ago to the ath5k list that did something similar,
> but I did:
>
>       if (changes & (BSS_CHANGED_BSSID | BSS_CHANGED_ASSOC)) {
>               ath5k_hw_set_associd(ah, ah->ah_bssid, ah->ah_aid);
>       }
>
> Thus if it changed regardless of the reason why, we update the mask.

Yeah might be a good idea to do it that way -- although upon disassoc
you should also just disable ps.

  Luis

^ permalink raw reply

* [PATCH 2.6.32] cfg80211: fix netns error unwinding bug
From: Johannes Berg @ 2009-10-08 19:02 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

The error unwinding code in set_netns has a bug
that will make it run into a BUG_ON if passed a
bad wiphy index, fix by not trying to unlock a
wiphy that doesn't exist.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 net/wireless/nl80211.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- wireless-testing.orig/net/wireless/nl80211.c	2009-10-06 16:15:18.000000000 +0200
+++ wireless-testing/net/wireless/nl80211.c	2009-10-06 16:15:28.000000000 +0200
@@ -4031,7 +4031,7 @@ static int nl80211_wiphy_netns(struct sk
 	rdev = cfg80211_get_dev_from_info(info);
 	if (IS_ERR(rdev)) {
 		err = PTR_ERR(rdev);
-		goto out;
+		goto out_rtnl;
 	}
 
 	net = get_net_ns_by_pid(pid);
@@ -4051,6 +4051,7 @@ static int nl80211_wiphy_netns(struct sk
 	put_net(net);
  out:
 	cfg80211_unlock_rdev(rdev);
+ out_rtnl:
 	rtnl_unlock();
 	return err;
 }



^ permalink raw reply

* [PATCH 18/20] wl1271: Enable beacon filtering with the stack
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Enable beacon filtering with the mac80211 stack.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h       |    2 ++
 drivers/net/wireless/wl12xx/wl1271_event.c |   14 ++++++++------
 drivers/net/wireless/wl12xx/wl1271_main.c  |   12 ++++++++++++
 3 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 34a52b3..96a5813 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -420,6 +420,8 @@ struct wl1271 {
 
 	struct wl1271_fw_status *fw_status;
 	struct wl1271_tx_hw_res_if *tx_res_if;
+
+	struct ieee80211_vif *vif;
 };
 
 int wl1271_plt_start(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 87055f7..f329276 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -70,14 +70,16 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
 			return ret;
 	}
 
-	if (vector & BSS_LOSE_EVENT_ID) {
+	/*
+	 * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon
+	 * filtering) is enabled. Without PSM, the stack will receive all
+	 * beacons and can detect beacon loss by itself.
+	 */
+	if (vector & BSS_LOSE_EVENT_ID && wl->psm) {
 		wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
 
-		if (wl->psm_requested && wl->psm) {
-			ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
-			if (ret < 0)
-				return ret;
-		}
+		/* indicate to the stack, that beacons have been lost */
+		ieee80211_beacon_loss(wl->vif);
 	}
 
 	return 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index d22de23..e6f9e9b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -665,6 +665,12 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
 		     conf->type, conf->mac_addr);
 
 	mutex_lock(&wl->mutex);
+	if (wl->vif) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	wl->vif = conf->vif;
 
 	switch (conf->type) {
 	case NL80211_IFTYPE_STATION:
@@ -688,7 +694,12 @@ out:
 static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
 					 struct ieee80211_if_init_conf *conf)
 {
+	struct wl1271 *wl = hw->priv;
+
+	mutex_lock(&wl->mutex);
 	wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
+	wl->vif = NULL;
+	mutex_unlock(&wl->mutex);
 }
 
 #if 0
@@ -1382,6 +1393,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 	wl->dtim_period = WL1271_DEFAULT_DTIM_PERIOD;
 	wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
 	wl->band = IEEE80211_BAND_2GHZ;
+	wl->vif = NULL;
 
 	for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
 		wl->tx_frames[i] = NULL;
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 06/20] wl1271: mask aid bits 14 and 15 in ps-poll template
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

In ps-poll template aid bits 14 and 15 were not masked as required by
the standard. Mask them so that aid is sent in correct format.

This patch is a direct port of the respective patch for the wl1251
driver by Kalle Valo.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Vidhya Govindan <vidhya.govindan@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_cmd.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 1ee1b2b..bd65b38 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -682,7 +682,10 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid)
 
 	memcpy(template.bssid, wl->bssid, ETH_ALEN);
 	memcpy(template.ta, wl->mac_addr, ETH_ALEN);
-	template.aid = aid;
+
+	/* aid in PS-Poll has its two MSBs each set to 1 */
+	template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid);
+
 	template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
 
 	return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template,
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 03/20] wl1271: Security sequence number handling for TX (for WPA)
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Add security sequence number handling to the driver TX data path needed
by WPA.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h      |    5 +++++
 drivers/net/wireless/wl12xx/wl1271_cmd.c  |   11 +++++++++--
 drivers/net/wireless/wl12xx/wl1271_cmd.h  |    3 ++-
 drivers/net/wireless/wl12xx/wl1271_main.c |   13 +++++++++++--
 drivers/net/wireless/wl12xx/wl1271_tx.c   |   11 +++++++++++
 5 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 55818f9..e575dcc 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -337,6 +337,11 @@ struct wl1271 {
 	/* Pending TX frames */
 	struct sk_buff *tx_frames[16];
 
+	/* Security sequence number counters */
+	u8 tx_security_last_seq;
+	u16 tx_security_seq_16;
+	u32 tx_security_seq_32;
+
 	/* FW Rx counter */
 	u32 rx_counter;
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 2a4351f..1ee1b2b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -228,6 +228,10 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
 
 	join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
 
+	/* reset TX security counters */
+	wl->tx_security_last_seq = 0;
+	wl->tx_security_seq_16 = 0;
+	wl->tx_security_seq_32 = 0;
 
 	ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
 	if (ret < 0) {
@@ -759,7 +763,8 @@ out:
 }
 
 int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
-		       u8 key_size, const u8 *key, const u8 *addr)
+		       u8 key_size, const u8 *key, const u8 *addr,
+		       u32 tx_seq_32, u16 tx_seq_16)
 {
 	struct wl1271_cmd_set_keys *cmd;
 	int ret = 0;
@@ -777,12 +782,14 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 	cmd->key_size = key_size;
 	cmd->key_type = key_type;
 
+	cmd->ac_seq_num16[0] = tx_seq_16;
+	cmd->ac_seq_num32[0] = tx_seq_32;
+
 	/* we have only one SSID profile */
 	cmd->ssid_profile = 0;
 
 	cmd->id = id;
 
-	/* FIXME: this is from wl1251, needs to be checked */
 	if (key_type == KEY_TKIP) {
 		/*
 		 * We get the key in the following form:
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 951a844..7c4d3aa 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -49,7 +49,8 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid);
 int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len);
 int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
 int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
-		       u8 key_size, const u8 *key, const u8 *addr);
+		       u8 key_size, const u8 *key, const u8 *addr,
+		       u32 tx_seq_32, u16 tx_seq_16);
 
 enum wl1271_commands {
 	CMD_INTERROGATE     = 1,    /*use this to read information elements*/
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 27298b1..bedd19b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -592,6 +592,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
 	wl->tx_blocks_available = 0;
 	wl->tx_results_count = 0;
 	wl->tx_packets_count = 0;
+	wl->tx_security_last_seq = 0;
+	wl->tx_security_seq_16 = 0;
+	wl->tx_security_seq_32 = 0;
 	wl->time_offset = 0;
 	wl->session_counter = 0;
 	for (i = 0; i < NUM_TX_QUEUES; i++)
@@ -823,6 +826,8 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	struct wl1271 *wl = hw->priv;
 	const u8 *addr;
 	int ret;
+	u32 tx_seq_32 = 0;
+	u16 tx_seq_16 = 0;
 	u8 key_type;
 
 	static const u8 bcast_addr[ETH_ALEN] =
@@ -861,11 +866,15 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		key_type = KEY_TKIP;
 
 		key_conf->hw_key_idx = key_conf->keyidx;
+		tx_seq_32 = wl->tx_security_seq_32;
+		tx_seq_16 = wl->tx_security_seq_16;
 		break;
 	case ALG_CCMP:
 		key_type = KEY_AES;
 
 		key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+		tx_seq_32 = wl->tx_security_seq_32;
+		tx_seq_16 = wl->tx_security_seq_16;
 		break;
 	default:
 		wl1271_error("Unknown key algo 0x%x", key_conf->alg);
@@ -879,7 +888,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
 					 key_conf->keyidx, key_type,
 					 key_conf->keylen, key_conf->key,
-					 addr);
+					 addr, tx_seq_32, tx_seq_16);
 		if (ret < 0) {
 			wl1271_error("Could not add or replace key");
 			goto out_sleep;
@@ -890,7 +899,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 		ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
 					 key_conf->keyidx, key_type,
 					 key_conf->keylen, key_conf->key,
-					 addr);
+					 addr, 0, 0);
 		if (ret < 0) {
 			wl1271_error("Could not remove key");
 			goto out_sleep;
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 0c19688..162f026 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -258,6 +258,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
 	struct ieee80211_tx_info *info;
 	struct sk_buff *skb;
 	u32 header_len;
+	u16 seq;
 	int id = result->id;
 
 	/* check for id legality */
@@ -284,6 +285,16 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
 	/* info->status.retry_count = result->ack_failures; */
 	wl->stats.retry_count += result->ack_failures;
 
+	/* update security sequence number */
+	seq = wl->tx_security_seq_16 +
+		(result->lsb_security_sequence_number -
+		 wl->tx_security_last_seq);
+	wl->tx_security_last_seq = result->lsb_security_sequence_number;
+
+	if (seq < wl->tx_security_seq_16)
+		wl->tx_security_seq_32++;
+	wl->tx_security_seq_16 = seq;
+
 	/* get header len */
 	if (info->control.hw_key &&
 	    info->control.hw_key->alg == ALG_TKIP)
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 19/20] wl1271: Configure beacon filtering on if PSM used
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Enable beacon filtering when PSM is enabled

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_acx.c  |   11 +++++++----
 drivers/net/wireless/wl12xx/wl1271_acx.h  |    7 ++++++-
 drivers/net/wireless/wl12xx/wl1271_init.c |    3 ++-
 drivers/net/wireless/wl12xx/wl1271_main.c |    3 ++-
 drivers/net/wireless/wl12xx/wl1271_ps.c   |   11 +++++++++++
 5 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 4b5fd94..b9dfa09 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -386,7 +386,7 @@ out:
 	return ret;
 }
 
-int wl1271_acx_beacon_filter_opt(struct wl1271 *wl)
+int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
 {
 	struct acx_beacon_filter_option *beacon_filter;
 	int ret;
@@ -399,7 +399,7 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl)
 		goto out;
 	}
 
-	beacon_filter->enable = 0;
+	beacon_filter->enable = enable_filter;
 	beacon_filter->max_num_beacons = 0;
 
 	ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
@@ -417,6 +417,7 @@ out:
 int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
 {
 	struct acx_beacon_filter_ie_table *ie_table;
+	int idx = 0;
 	int ret;
 
 	wl1271_debug(DEBUG_ACX, "acx beacon filter table");
@@ -427,8 +428,10 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
 		goto out;
 	}
 
-	ie_table->num_ie = 0;
-	memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE);
+	/* configure default beacon pass-through rules */
+	ie_table->num_ie = 1;
+	ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN;
+	ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE;
 
 	ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
 				   ie_table, sizeof(*ie_table));
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index bb21bcb..0c2a107 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -398,6 +398,11 @@ struct acx_beacon_filter_option {
 			   (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \
 			    BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE))
 
+#define BEACON_RULE_PASS_ON_CHANGE                     BIT(0)
+#define BEACON_RULE_PASS_ON_APPEARANCE                 BIT(1)
+
+#define BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN         (37)
+
 struct acx_beacon_filter_ie_table {
 	struct acx_header header;
 
@@ -1206,7 +1211,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
 				 void *mc_list, u32 mc_list_len);
 int wl1271_acx_service_period_timeout(struct wl1271 *wl);
 int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
-int wl1271_acx_beacon_filter_opt(struct wl1271 *wl);
+int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter);
 int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
 int wl1271_acx_conn_monit_params(struct wl1271 *wl);
 int wl1271_acx_sg_enable(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index d3db3fb..bf4d0e1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -136,7 +136,8 @@ static int wl1271_init_beacon_filter(struct wl1271 *wl)
 {
 	int ret;
 
-	ret = wl1271_acx_beacon_filter_opt(wl);
+	/* disable beacon filtering at this stage */
+	ret = wl1271_acx_beacon_filter_opt(wl, false);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index e6f9e9b..3662715 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1319,7 +1319,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
 	wl->hw->channel_change_time = 10000;
 
 	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
-		IEEE80211_HW_NOISE_DBM;
+		IEEE80211_HW_NOISE_DBM |
+		IEEE80211_HW_BEACON_FILTER;
 
 	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 	wl->hw->wiphy->max_scan_ssids = 1;
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index 0f6ea16..5580e53 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -129,6 +129,12 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
 	switch (mode) {
 	case STATION_POWER_SAVE_MODE:
 		wl1271_debug(DEBUG_PSM, "entering psm");
+
+		/* enable beacon filtering */
+		ret = wl1271_acx_beacon_filter_opt(wl, true);
+		if (ret < 0)
+			return ret;
+
 		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
 		if (ret < 0)
 			return ret;
@@ -146,6 +152,11 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
 		if (ret < 0)
 			return ret;
 
+		/* disable beacon filtering */
+		ret = wl1271_acx_beacon_filter_opt(wl, false);
+		if (ret < 0)
+			return ret;
+
 		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
 		if (ret < 0)
 			return ret;
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 00/20] First batch of new patches for wl1271
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

Hi John et al,

We have finally upgraded our internal kernel to 2.6.32, so I now had the time
to continue working on forward porting the patches we have been working on
internally, on top of 2.6.28.  There are 61 patches in total, so I decided to
break them down into separate patch sets, so that it's a bit easier to review.

Here's the first batch.  There are multiple fixes, improvements and updates for
a new firmware release (which has some API changes).

I'll wait until these patches cook a little bit before I send the next bunch.

Cheers,
Luca.

Juuso Oikarinen (17):
  wl1271: Correction to TX block allocation calculation
  wl1271: Security sequence number handling for TX (for WPA)
  wl1271: Correct TKIP header space handling in TX path
  wl1271: Implement delayed entry into ELP
  wl1271: mask aid bits 14 and 15 in ps-poll template
  wl1271: Implementation for SPI busy word checking
  wl1271: Configure rate policies based on AP rates
  wl1271: Update join usage
  wl1271: Corrections to TX path
  wl1271: use workqueue provided by mac80211 instead of the default
  wl1271: Clear probe-request template after scan
  wl1271: Multicast filtering configuration
  wl1271: Use vmalloc to allocate memory for firmware
  wl1271: Add connection monitoring configuration
  wl1271: Enable beacon filtering with the stack
  wl1271: Configure beacon filtering on if PSM used
  wl1271: Mask unneeded events from firmware to conserve power

Luciano Coelho (3):
  wl1271: remove unecessary qual parameter from rx status
  wl1271: added Juuso Oikarinen as module author
  wl1271: hack to disable filters

 drivers/net/wireless/wl12xx/wl1271.h       |   42 +++++-
 drivers/net/wireless/wl12xx/wl1271_acx.c   |   54 +++++--
 drivers/net/wireless/wl12xx/wl1271_acx.h   |   29 +++-
 drivers/net/wireless/wl12xx/wl1271_boot.c  |   21 ++-
 drivers/net/wireless/wl12xx/wl1271_cmd.c   |   40 +++--
 drivers/net/wireless/wl12xx/wl1271_cmd.h   |    6 +-
 drivers/net/wireless/wl12xx/wl1271_event.c |   18 ++-
 drivers/net/wireless/wl12xx/wl1271_init.c  |   13 ++-
 drivers/net/wireless/wl12xx/wl1271_main.c  |  244 +++++++++++++++++++++++-----
 drivers/net/wireless/wl12xx/wl1271_ps.c    |   57 +++++--
 drivers/net/wireless/wl12xx/wl1271_ps.h    |    2 +-
 drivers/net/wireless/wl12xx/wl1271_rx.c    |    6 -
 drivers/net/wireless/wl12xx/wl1271_spi.c   |   69 ++++++++-
 drivers/net/wireless/wl12xx/wl1271_tx.c    |   48 ++++--
 14 files changed, 517 insertions(+), 132 deletions(-)


^ permalink raw reply

* [PATCH 16/20] wl1271: Use vmalloc to allocate memory for firmware
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Use vmalloc to allocate memory for the firmware image, and use a smaller
linear buffer for the actual transfer of the firmware to the chipset.

This patch is an adaptation of a similar patch for wl1251 by Kalle Valo.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_boot.c |   16 ++++++++++++----
 drivers/net/wireless/wl12xx/wl1271_main.c |    5 +++--
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index 8228ef4..7640313 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -94,7 +94,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
 					     size_t fw_data_len, u32 dest)
 {
 	int addr, chunk_num, partition_limit;
-	u8 *p;
+	u8 *p, *chunk;
 
 	/* whal_FwCtrl_LoadFwImageSm() */
 
@@ -103,12 +103,17 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
 	wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d",
 		     fw_data_len, CHUNK_SIZE);
 
-
 	if ((fw_data_len % 4) != 0) {
 		wl1271_error("firmware length not multiple of four");
 		return -EIO;
 	}
 
+	chunk = kmalloc(CHUNK_SIZE, GFP_KERNEL);
+	if (!buf) {
+		wl1271_error("allocation for firmware upload chunk failed");
+		return -ENOMEM;
+	}
+
 	wl1271_set_partition(wl, dest,
 			     part_table[PART_DOWN].mem.size,
 			     part_table[PART_DOWN].reg.start,
@@ -137,9 +142,10 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
 		/* 10.3 upload the chunk */
 		addr = dest + chunk_num * CHUNK_SIZE;
 		p = buf + chunk_num * CHUNK_SIZE;
+		memcpy(chunk, p, CHUNK_SIZE);
 		wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
 			     p, addr);
-		wl1271_spi_mem_write(wl, addr, p, CHUNK_SIZE);
+		wl1271_spi_mem_write(wl, addr, chunk, CHUNK_SIZE);
 
 		chunk_num++;
 	}
@@ -147,10 +153,12 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
 	/* 10.4 upload the last chunk */
 	addr = dest + chunk_num * CHUNK_SIZE;
 	p = buf + chunk_num * CHUNK_SIZE;
+	memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
 	wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
 		     fw_data_len % CHUNK_SIZE, p, addr);
-	wl1271_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
+	wl1271_spi_mem_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE);
 
+	kfree(chunk);
 	return 0;
 }
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 09fe968..d22de23 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -30,6 +30,7 @@
 #include <linux/spi/spi.h>
 #include <linux/crc32.h>
 #include <linux/etherdevice.h>
+#include <linux/vmalloc.h>
 #include <linux/spi/wl12xx.h>
 
 #include "wl1271.h"
@@ -231,7 +232,7 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
 	}
 
 	wl->fw_len = fw->size;
-	wl->fw = kmalloc(wl->fw_len, GFP_KERNEL);
+	wl->fw = vmalloc(wl->fw_len);
 
 	if (!wl->fw) {
 		wl1271_error("could not allocate memory for the firmware");
@@ -1484,7 +1485,7 @@ static int __devexit wl1271_remove(struct spi_device *spi)
 	platform_device_unregister(&wl1271_device);
 	free_irq(wl->irq, wl);
 	kfree(wl->target_mem_map);
-	kfree(wl->fw);
+	vfree(wl->fw);
 	wl->fw = NULL;
 	kfree(wl->nvs);
 	wl->nvs = NULL;
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 20/20] wl1271: Mask unneeded events from firmware to conserve power
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Currently several events are enabled from the firmware for which there
is no handling. This wakes up the host unnecessarily. Mask those
unneeded events.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_boot.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index 7640313..140e943 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -390,8 +390,9 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 	/* enable gpio interrupts */
 	wl1271_boot_enable_interrupts(wl);
 
-	/* unmask all mbox events  */
-	wl->event_mask = 0xffffffff;
+	/* unmask required mbox events  */
+	wl->event_mask = BSS_LOSE_EVENT_ID |
+		SCAN_COMPLETE_EVENT_ID;
 
 	ret = wl1271_event_unmask(wl);
 	if (ret < 0) {
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 15/20] wl1271: Multicast filtering configuration
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Enable multicast filtering. This way by default no multicast frames will
reach the host, and when needed, only required multicast frames can be
passed from the WLAN chipset to the host.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h      |    7 +-
 drivers/net/wireless/wl12xx/wl1271_acx.c  |    9 +-
 drivers/net/wireless/wl12xx/wl1271_acx.h  |    8 +-
 drivers/net/wireless/wl12xx/wl1271_init.c |    2 +-
 drivers/net/wireless/wl12xx/wl1271_main.c |  121 +++++++++++++++++++++++++----
 5 files changed, 120 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 0b4744d..34a52b3 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -97,7 +97,8 @@ enum {
 	} while (0)
 
 #define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN |	\
-				  CFG_BSSID_FILTER_EN)
+				  CFG_BSSID_FILTER_EN | \
+				  CFG_MC_FILTER_EN)
 
 #define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN |  \
 				  CFG_RX_MGMT_EN | CFG_RX_DATA_EN |   \
@@ -123,7 +124,7 @@ enum {
 #define WL1271_DEFAULT_BEACON_INT  100
 #define WL1271_DEFAULT_DTIM_PERIOD 1
 
-#define ACX_TX_DESCRIPTORS    32
+#define ACX_TX_DESCRIPTORS         32
 
 enum wl1271_state {
 	WL1271_STATE_OFF,
@@ -345,7 +346,9 @@ struct wl1271 {
 	bool tx_queue_stopped;
 
 	struct work_struct tx_work;
+
 	struct work_struct filter_work;
+	struct wl1271_filter_params *filter_params;
 
 	/* Pending TX frames */
 	struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 2ae1081..a457123 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -300,7 +300,8 @@ out:
 	return ret;
 }
 
-int wl1271_acx_group_address_tbl(struct wl1271 *wl)
+int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
+				 void *mc_list, u32 mc_list_len)
 {
 	struct acx_dot11_grp_addr_tbl *acx;
 	int ret;
@@ -314,9 +315,9 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl)
 	}
 
 	/* MAC filtering */
-	acx->enabled = 0;
-	acx->num_groups = 0;
-	memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
+	acx->enabled = enable;
+	acx->num_groups = mc_list_len;
+	memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
 
 	ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
 				   acx, sizeof(*acx));
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index c177345..dae1fed 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -301,8 +301,8 @@ struct acx_slot {
 } __attribute__ ((packed));
 
 
-#define ADDRESS_GROUP_MAX	(8)
-#define ADDRESS_GROUP_MAX_LEN	(ETH_ALEN * ADDRESS_GROUP_MAX)
+#define ACX_MC_ADDRESS_GROUP_MAX	(8)
+#define ADDRESS_GROUP_MAX_LEN	        (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX)
 
 struct acx_dot11_grp_addr_tbl {
 	struct acx_header header;
@@ -313,7 +313,6 @@ struct acx_dot11_grp_addr_tbl {
 	u8 mac_table[ADDRESS_GROUP_MAX_LEN];
 } __attribute__ ((packed));
 
-
 #define  RX_TIMEOUT_PS_POLL_MIN    0
 #define  RX_TIMEOUT_PS_POLL_MAX    (200000)
 #define  RX_TIMEOUT_PS_POLL_DEF    (15)
@@ -1193,7 +1192,8 @@ int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time);
 int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
 int wl1271_acx_pd_threshold(struct wl1271 *wl);
 int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
-int wl1271_acx_group_address_tbl(struct wl1271 *wl);
+int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
+				 void *mc_list, u32 mc_list_len);
 int wl1271_acx_service_period_timeout(struct wl1271 *wl);
 int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
 int wl1271_acx_beacon_filter_opt(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index eb6b91a..49ff407 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -117,7 +117,7 @@ static int wl1271_init_phy_config(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_acx_group_address_tbl(wl);
+	ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index d104230..09fe968 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -379,12 +379,39 @@ out:
 	return ret;
 }
 
+struct wl1271_filter_params {
+	unsigned int filters;
+	unsigned int changed;
+	int mc_list_length;
+	u8 mc_list[ACX_MC_ADDRESS_GROUP_MAX][ETH_ALEN];
+};
+
+#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
+				  FIF_ALLMULTI | \
+				  FIF_FCSFAIL | \
+				  FIF_BCN_PRBRESP_PROMISC | \
+				  FIF_CONTROL | \
+				  FIF_OTHER_BSS)
+
 static void wl1271_filter_work(struct work_struct *work)
 {
 	struct wl1271 *wl =
 		container_of(work, struct wl1271, filter_work);
+	struct wl1271_filter_params *fp;
+	unsigned long flags;
+	bool enabled = true;
 	int ret;
 
+	/* first, get the filter parameters */
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	fp = wl->filter_params;
+	wl->filter_params = NULL;
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+	if (!fp)
+		return;
+
+	/* then, lock the mutex without risk of lock-up */
 	mutex_lock(&wl->mutex);
 
 	if (wl->state == WL1271_STATE_OFF)
@@ -394,6 +421,20 @@ static void wl1271_filter_work(struct work_struct *work)
 	if (ret < 0)
 		goto out;
 
+	/* configure the mc filter regardless of the changed flags */
+	if (fp->filters & FIF_ALLMULTI)
+		enabled = false;
+
+	ret = wl1271_acx_group_address_tbl(wl, enabled,
+					   fp->mc_list, fp->mc_list_length);
+	if (ret < 0)
+		goto out_sleep;
+
+	/* determine, whether supported filter values have changed */
+	if (fp->changed == 0)
+		goto out;
+
+	/* apply configured filters */
 	ret = wl1271_cmd_join(wl);
 	if (ret < 0)
 		goto out_sleep;
@@ -403,6 +444,7 @@ out_sleep:
 
 out:
 	mutex_unlock(&wl->mutex);
+	kfree(fp);
 }
 
 int wl1271_plt_start(struct wl1271 *wl)
@@ -544,12 +586,20 @@ out:
 static void wl1271_op_stop(struct ieee80211_hw *hw)
 {
 	struct wl1271 *wl = hw->priv;
+	unsigned long flags;
 	int i;
 
 	wl1271_info("down");
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
 
+	/* complete/cancel ongoing work */
+	cancel_work_sync(&wl->filter_work);
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	kfree(wl->filter_params);
+	wl->filter_params = NULL;
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
 	mutex_lock(&wl->mutex);
 
 	WARN_ON(wl->state != WL1271_STATE_ON);
@@ -784,16 +834,52 @@ out:
 	return ret;
 }
 
-#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
-				  FIF_ALLMULTI | \
-				  FIF_FCSFAIL | \
-				  FIF_BCN_PRBRESP_PROMISC | \
-				  FIF_CONTROL | \
-				  FIF_OTHER_BSS)
+static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
+				       struct dev_addr_list *mc_list)
+{
+	struct wl1271 *wl = hw->priv;
+	struct wl1271_filter_params *fp;
+	unsigned long flags;
+	int i;
+
+	/*
+	 * FIXME: we should return a hash that will be passed to
+	 * configure_filter() instead of saving everything in the context.
+	 */
+
+	fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+	if (!fp) {
+		wl1271_error("Out of memory setting filters.");
+		return 0;
+	}
+
+	/* update multicast filtering parameters */
+	if (mc_count > ACX_MC_ADDRESS_GROUP_MAX) {
+		mc_count = 0;
+		fp->filters |= FIF_ALLMULTI;
+	}
+
+	fp->mc_list_length = 0;
+	for (i = 0; i < mc_count; i++) {
+		if (mc_list->da_addrlen == ETH_ALEN) {
+			memcpy(fp->mc_list[fp->mc_list_length],
+			       mc_list->da_addr, ETH_ALEN);
+			fp->mc_list_length++;
+		} else
+			wl1271_warning("Unknown mc address length.");
+	}
+
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	kfree(wl->filter_params);
+	wl->filter_params = fp;
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+	return 1;
+}
 
 static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
 				       unsigned int changed,
-				       unsigned int *total,u64 multicast)
+				       unsigned int *total, u64 multicast)
 {
 	struct wl1271 *wl = hw->priv;
 
@@ -802,19 +888,21 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
 	*total &= WL1271_SUPPORTED_FILTERS;
 	changed &= WL1271_SUPPORTED_FILTERS;
 
-	if (changed == 0)
+	if (!multicast)
 		return;
 
-	/* FIXME: wl->rx_config and wl->rx_filter are not protected */
-	wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
-	wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
-
 	/*
-	 * FIXME: workqueues need to be properly cancelled on stop(), for
-	 * now let's just disable changing the filter settings. They will
-	 * be updated any on config().
+	 * FIXME: for now we are still using a workqueue for filter
+	 * configuration, but with the new mac80211, this is not needed,
+	 * since configure_filter can now sleep.  We now have
+	 * prepare_multicast, which needs to be atomic instead.
 	 */
-	/* schedule_work(&wl->filter_work); */
+
+	/* store current filter config */
+	wl->filter_params->filters = *total;
+	wl->filter_params->changed = changed;
+
+	ieee80211_queue_work(wl->hw, &wl->filter_work);
 }
 
 static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -1177,6 +1265,7 @@ static const struct ieee80211_ops wl1271_ops = {
 	.remove_interface = wl1271_op_remove_interface,
 	.config = wl1271_op_config,
 /* 	.config_interface = wl1271_op_config_interface, */
+	.prepare_multicast = wl1271_op_prepare_multicast,
 	.configure_filter = wl1271_op_configure_filter,
 	.tx = wl1271_op_tx,
 	.set_key = wl1271_op_set_key,
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 17/20] wl1271: Add connection monitoring configuration
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Add configuration for connection monitor (number of allowed beacons, and
timeout after last received beacon.)

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_acx.c  |   30 +++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/wl1271_acx.h  |   11 ++++++++++
 drivers/net/wireless/wl12xx/wl1271_init.c |    6 +++++
 3 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index a457123..4b5fd94 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -442,6 +442,36 @@ out:
 	return ret;
 }
 
+int wl1271_acx_conn_monit_params(struct wl1271 *wl)
+{
+	struct acx_conn_monit_params *acx;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx connection monitor parameters");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD;
+	acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT;
+
+	ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("failed to set connection monitor "
+			       "parameters: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+
 int wl1271_acx_sg_enable(struct wl1271 *wl)
 {
 	struct acx_bt_wlan_coex *pta;
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index dae1fed..bb21bcb 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -406,6 +406,16 @@ struct acx_beacon_filter_ie_table {
 	u8 pad[3];
 } __attribute__ ((packed));
 
+#define SYNCH_FAIL_DEFAULT_THRESHOLD    5     /* number of beacons */
+#define NO_BEACON_DEFAULT_TIMEOUT       (100) /* TU */
+
+struct acx_conn_monit_params {
+       struct acx_header header;
+
+       u32 synch_fail_thold; /* number of beacons missed */
+       u32 bss_lose_timeout; /* number of TU's from synch fail */
+};
+
 enum {
 	SG_ENABLE = 0,
 	SG_DISABLE,
@@ -1198,6 +1208,7 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl);
 int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
 int wl1271_acx_beacon_filter_opt(struct wl1271 *wl);
 int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
+int wl1271_acx_conn_monit_params(struct wl1271 *wl);
 int wl1271_acx_sg_enable(struct wl1271 *wl);
 int wl1271_acx_sg_cfg(struct wl1271 *wl);
 int wl1271_acx_cca_threshold(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 49ff407..d3db3fb 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -323,6 +323,11 @@ int wl1271_hw_init(struct wl1271 *wl)
 	if (ret < 0)
 		goto out_free_memmap;
 
+	/* Initialize connection monitoring thresholds */
+	ret = wl1271_acx_conn_monit_params(wl);
+	if (ret < 0)
+		goto out_free_memmap;
+
 	/* Beacon filtering */
 	ret = wl1271_init_beacon_filter(wl);
 	if (ret < 0)
@@ -392,6 +397,7 @@ int wl1271_hw_init(struct wl1271 *wl)
 
  out_free_memmap:
 	kfree(wl->target_mem_map);
+	wl->target_mem_map = NULL;
 
 	return ret;
 }
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 12/20] wl1271: hack to disable filters
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Kalle Valo
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

This is a hack to disable all filters in the join command.  This is based on
Kalle Valo's patch for wl1251.

Cc: Kalle Valo <kalle.valo@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_cmd.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 35a6e67..ac93efd 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -208,6 +208,15 @@ int wl1271_cmd_join(struct wl1271 *wl)
 	join->rx_config_options = wl->rx_config;
 	join->rx_filter_options = wl->rx_filter;
 
+	/*
+	 * FIXME: disable temporarily all filters because after commit
+	 * 9cef8737 "mac80211: fix managed mode BSSID handling" broke
+	 * association. The filter logic needs to be implemented properly
+	 * and once that is done, this hack can be removed.
+	 */
+	join->rx_config_options = 0;
+	join->rx_filter_options = WL1271_DEFAULT_RX_FILTER;
+
 	join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
 		RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
 
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 13/20] wl1271: use workqueue provided by mac80211 instead of the default
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Use the workqueue provided by the mac80211 stack instead of the system
default queue.

Modified to use new ieee_queue_work() as required by changes in the
stack.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_main.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 1a0491a..d104230 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -107,7 +107,7 @@ static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
 
 	/* if more blocks are available now, schedule some tx work */
 	if (total && !skb_queue_empty(&wl->tx_queue))
-		schedule_work(&wl->tx_work);
+		ieee80211_queue_work(wl->hw, &wl->tx_work);
 
 	/* update the host-chipset time offset */
 	wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
@@ -205,7 +205,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
 		wl->elp_compl = NULL;
 	}
 
-	schedule_work(&wl->irq_work);
+	ieee80211_queue_work(wl->hw, &wl->irq_work);
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
 	return IRQ_HANDLED;
@@ -480,7 +480,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	 * before that, the tx_work will not be initialized!
 	 */
 
-	schedule_work(&wl->tx_work);
+	ieee80211_queue_work(wl->hw, &wl->tx_work);
 
 	/*
 	 * The workqueue is slow to process the tx_queue and we need stop
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 09/20] wl1271: Update join usage
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Update the usage of join's, including using actual beacon interval and
dtim from AP, and configuring a basic rate set from AP.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271.h      |   12 ++++++++
 drivers/net/wireless/wl12xx/wl1271_cmd.c  |   15 +++-------
 drivers/net/wireless/wl12xx/wl1271_cmd.h  |    3 +-
 drivers/net/wireless/wl12xx/wl1271_main.c |   42 ++++++++++++++++++++++-------
 4 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 671dc5a..05eb29c 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -104,6 +104,8 @@ enum {
 				  CFG_RX_CTL_EN | CFG_RX_BCN_EN |     \
 				  CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
 
+#define WL1271_DEFAULT_BASIC_RATE_SET (ACX_RATE_MASK_ALL)
+
 #define WL1271_FW_NAME "wl1271-fw.bin"
 #define WL1271_NVS_NAME "wl1271-nvs.bin"
 
@@ -118,6 +120,9 @@ enum {
 #define WL1271_ELP_HW_STATE_ASLEEP 0
 #define WL1271_ELP_HW_STATE_IRQ    1
 
+#define WL1271_DEFAULT_BEACON_INT  100
+#define WL1271_DEFAULT_DTIM_PERIOD 1
+
 enum wl1271_state {
 	WL1271_STATE_OFF,
 	WL1271_STATE_ON,
@@ -369,6 +374,13 @@ struct wl1271 {
 	/* Our association ID */
 	u16 aid;
 
+	/* Beacon parameters */
+	u16 beacon_int;
+	u8 dtim_period;
+
+	/* currently configured rate set */
+	u32 basic_rate_set;
+
 	/* The current band */
 	enum ieee80211_band band;
 
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index bd65b38..35a6e67 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -175,11 +175,9 @@ int wl1271_cmd_cal(struct wl1271 *wl)
 	return ret;
 }
 
-int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
-		    u16 beacon_interval, u8 wait)
+int wl1271_cmd_join(struct wl1271 *wl)
 {
 	static bool do_cal = true;
-	unsigned long timeout;
 	struct wl1271_cmd_join *join;
 	int ret, i;
 	u8 *bssid;
@@ -213,9 +211,9 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
 	join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
 		RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
 
-	join->beacon_interval = beacon_interval;
-	join->dtim_interval = dtim_interval;
-	join->bss_type = bss_type;
+	join->beacon_interval = wl->beacon_int;
+	join->dtim_interval = wl->dtim_period;
+	join->bss_type = wl->bss_type;
 	join->channel = wl->channel;
 	join->ssid_len = wl->ssid_len;
 	memcpy(join->ssid, wl->ssid, wl->ssid_len);
@@ -239,14 +237,11 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
 		goto out_free;
 	}
 
-	timeout = msecs_to_jiffies(JOIN_TIMEOUT);
-
 	/*
 	 * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
 	 * simplify locking we just sleep instead, for now
 	 */
-	if (wait)
-		msleep(10);
+	msleep(10);
 
 out_free:
 	kfree(join);
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 7c4d3aa..63bc441 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -30,8 +30,7 @@
 struct acx_header;
 
 int wl1271_cmd_send(struct wl1271 *wl, u16 type, void *buf, size_t buf_len);
-int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
-		    u16 beacon_interval, u8 wait);
+int wl1271_cmd_join(struct wl1271 *wl);
 int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index b9b1c20..6e35fcf 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -394,8 +394,7 @@ static void wl1271_filter_work(struct work_struct *work)
 	if (ret < 0)
 		goto out;
 
-	/* FIXME: replace the magic numbers with proper definitions */
-	ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0);
+	ret = wl1271_cmd_join(wl);
 	if (ret < 0)
 		goto out_sleep;
 
@@ -672,8 +671,7 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
 		memcpy(wl->ssid, conf->ssid, wl->ssid_len);
 
 	if (wl->bss_type != BSS_TYPE_IBSS) {
-		/* FIXME: replace the magic numbers with proper definitions */
-		ret = wl1271_cmd_join(wl, wl->bss_type, 5, 100, 1);
+		ret = wl1271_cmd_join(wl);
 		if (ret < 0)
 			goto out_sleep;
 	}
@@ -696,8 +694,7 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
 		if (ret < 0)
 			goto out_sleep;
 
-		/* FIXME: replace the magic numbers with proper definitions */
-		ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0);
+		ret = wl1271_cmd_join(wl);
 
 		if (ret < 0)
 			goto out_sleep;
@@ -738,8 +735,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
 		u8 old_channel = wl->channel;
 		wl->channel = channel;
 
-		/* FIXME: use beacon interval provided by mac80211 */
-		ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0);
+		ret = wl1271_cmd_join(wl);
 		if (ret < 0) {
 			wl->channel = old_channel;
 			goto out_sleep;
@@ -1016,8 +1012,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 
 	if (changed & BSS_CHANGED_ASSOC) {
 		if (bss_conf->assoc) {
+			wl->beacon_int = bss_conf->beacon_int;
+			wl->dtim_period = bss_conf->dtim_period;
 			wl->aid = bss_conf->aid;
 
+			ret = wl1271_cmd_join(wl);
+			if (ret < 0) {
+				wl1271_warning("Association configuration "
+					       "failed %d", ret);
+				goto out_sleep;
+			}
+
 			ret = wl1271_cmd_build_ps_poll(wl, wl->aid);
 			if (ret < 0)
 				goto out_sleep;
@@ -1033,7 +1038,14 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 				if (ret < 0)
 					goto out_sleep;
 			}
+		} else {
+			/* use defaults when not associated */
+			wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
+			wl->dtim_period = WL1271_DEFAULT_DTIM_PERIOD;
+			wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
+			wl->aid = 0;
 		}
+
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
@@ -1066,13 +1078,20 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 	}
 
 	if (changed & BSS_CHANGED_BASIC_RATES) {
-		u32 enabled_rates = wl1271_enabled_rates_get(
+		wl->basic_rate_set = wl1271_enabled_rates_get(
 			wl, bss_conf->basic_rates);
-		ret = wl1271_acx_rate_policies(wl, enabled_rates);
+		ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set);
+
 		if (ret < 0) {
 			wl1271_warning("Set rate policies failed %d", ret);
 			goto out_sleep;
 		}
+		ret = wl1271_cmd_join(wl);
+		if (ret < 0) {
+			wl1271_warning("Join with new basic rate "
+				       "set failed %d", ret);
+			goto out_sleep;
+		}
 	}
 
 out_sleep:
@@ -1269,6 +1288,9 @@ static int __devinit wl1271_probe(struct spi_device *spi)
 	wl->psm_requested = false;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
+	wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
+	wl->dtim_period = WL1271_DEFAULT_DTIM_PERIOD;
+	wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;
 	wl->band = IEEE80211_BAND_2GHZ;
 
 	/* We use the default power on sleep time until we know which chip
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 14/20] wl1271: Clear probe-request template after scan
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

From: Juuso Oikarinen <juuso.oikarinen@nokia.com>

Clear the probe-request template on the firmware after scan. Unless
cleared, the firmware can independently send probe requests to the AP
and interfere with the mac80211 logic.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_event.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index f3afd4a..87055f7 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -26,6 +26,7 @@
 #include "wl1271_spi.h"
 #include "wl1271_event.h"
 #include "wl1271_ps.h"
+#include "wl12xx_80211.h"
 
 static int wl1271_event_scan_complete(struct wl1271 *wl,
 				      struct event_mailbox *mbox)
@@ -34,6 +35,9 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
 		     mbox->scheduled_scan_status);
 
 	if (wl->scanning) {
+		int size = sizeof(struct wl12xx_probe_req_template);
+		wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
+					size);
 		mutex_unlock(&wl->mutex);
 		ieee80211_scan_completed(wl->hw, false);
 		mutex_lock(&wl->mutex);
-- 
1.5.6.5


^ permalink raw reply related

* [PATCH 11/20] wl1271: added Juuso Oikarinen as module author
From: Luciano Coelho @ 2009-10-08 18:56 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Juuso Oikarinen
In-Reply-To: <1255028196-6565-1-git-send-email-luciano.coelho@nokia.com>

Add Juuso as one of the module authors, since he's working heavily on this
module as well.

Cc: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
---
 drivers/net/wireless/wl12xx/wl1271_main.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 0a0f2ea..1a0491a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1449,3 +1449,4 @@ module_exit(wl1271_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
+MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
-- 
1.5.6.5


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox