zd1211rw: let zd_set_beacon_interval() set dtim_period and add AP-beacon flag
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>
Mon, 31 Jan 2011 18:48:25 +0000 (20:48 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 4 Feb 2011 21:29:49 +0000 (16:29 -0500)
Add support for AP-mode beacon. Also disable beacon when interface is set
down as otherwise hw will keep flooding NEXT_BCN interrupts.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/zd1211rw/zd_chip.c
drivers/net/wireless/zd1211rw/zd_chip.h
drivers/net/wireless/zd1211rw/zd_mac.c

index 71d3cdebca148b851b1b1b9b634188f7225ec743..d8dc92711f405b9d10cba838adfa6a7159ccaff5 100644 (file)
@@ -888,14 +888,36 @@ static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
 }
 
 
-static int set_beacon_interval(struct zd_chip *chip, u32 interval)
+static int set_beacon_interval(struct zd_chip *chip, u16 interval,
+                              u8 dtim_period, int type)
 {
        int r;
        struct aw_pt_bi s;
+       u32 b_interval, mode_flag;
 
        ZD_ASSERT(mutex_is_locked(&chip->mutex));
 
-       r = zd_iowrite32_locked(chip, interval, CR_BCN_INTERVAL);
+       if (interval > 0) {
+               switch (type) {
+               case NL80211_IFTYPE_ADHOC:
+               case NL80211_IFTYPE_MESH_POINT:
+                       mode_flag = BCN_MODE_IBSS;
+                       break;
+               case NL80211_IFTYPE_AP:
+                       mode_flag = BCN_MODE_AP;
+                       break;
+               default:
+                       mode_flag = 0;
+                       break;
+               }
+       } else {
+               dtim_period = 0;
+               mode_flag = 0;
+       }
+
+       b_interval = mode_flag | (dtim_period << 16) | interval;
+
+       r = zd_iowrite32_locked(chip, b_interval, CR_BCN_INTERVAL);
        if (r)
                return r;
        r = get_aw_pt_bi(chip, &s);
@@ -904,12 +926,13 @@ static int set_beacon_interval(struct zd_chip *chip, u32 interval)
        return set_aw_pt_bi(chip, &s);
 }
 
-int zd_set_beacon_interval(struct zd_chip *chip, u32 interval)
+int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
+                          int type)
 {
        int r;
 
        mutex_lock(&chip->mutex);
-       r = set_beacon_interval(chip, interval);
+       r = set_beacon_interval(chip, interval, dtim_period, type);
        mutex_unlock(&chip->mutex);
        return r;
 }
@@ -928,7 +951,7 @@ static int hw_init(struct zd_chip *chip)
        if (r)
                return r;
 
-       return set_beacon_interval(chip, 100);
+       return set_beacon_interval(chip, 100, 0, NL80211_IFTYPE_UNSPECIFIED);
 }
 
 static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset)
index 7b0c58ce705602c3eda52051a19eff1828ab8586..14e4402a6111bdb5b70745f7d4784693eb30dfa9 100644 (file)
@@ -546,6 +546,7 @@ enum {
 #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
        RX_FILTER_CFEND | RX_FILTER_CFACK)
 
+#define BCN_MODE_AP                    0x1000000
 #define BCN_MODE_IBSS                  0x2000000
 
 /* Monitor mode sets filter to 0xfffff */
@@ -921,7 +922,8 @@ enum led_status {
 
 int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
 
-int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
+int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
+                          int type);
 
 static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
 {
index 84ac95eb59fafc2d961fa4a845e9c7c66e2553cc..1bd275bc6084312d4f24909236f255df006b4305 100644 (file)
@@ -926,7 +926,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
        struct zd_mac *mac = zd_hw_mac(hw);
        mac->type = NL80211_IFTYPE_UNSPECIFIED;
        mac->vif = NULL;
-       zd_set_beacon_interval(&mac->chip, 0);
+       zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
        zd_write_mac_addr(&mac->chip, NULL);
 }
 
@@ -1058,15 +1058,16 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
                }
 
                if (changes & BSS_CHANGED_BEACON_ENABLED) {
-                       u32 interval;
+                       u16 interval = 0;
+                       u8 period = 0;
 
-                       if (bss_conf->enable_beacon)
-                               interval = BCN_MODE_IBSS |
-                                               bss_conf->beacon_int;
-                       else
-                               interval = 0;
+                       if (bss_conf->enable_beacon) {
+                               period = bss_conf->dtim_period;
+                               interval = bss_conf->beacon_int;
+                       }
 
-                       zd_set_beacon_interval(&mac->chip, interval);
+                       zd_set_beacon_interval(&mac->chip, interval, period,
+                                              mac->type);
                }
        } else
                associated = is_valid_ether_addr(bss_conf->bssid);