zd1211rw: support setting BSSID for AP mode
authorJussi Kivilinna <jussi.kivilinna@mbnet.fi>
Mon, 31 Jan 2011 18:48:06 +0000 (20:48 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 4 Feb 2011 21:29:49 +0000 (16:29 -0500)
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
drivers/net/wireless/zd1211rw/zd_mac.h

index 447f2360b0caf02d989490e7460addeb50e76620..71d3cdebca148b851b1b1b9b634188f7225ec743 100644 (file)
@@ -370,16 +370,12 @@ error:
        return r;
 }
 
-/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
- *              CR_MAC_ADDR_P2 must be overwritten
- */
-int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+static int zd_write_mac_addr_common(struct zd_chip *chip, const u8 *mac_addr,
+                                   const struct zd_ioreq32 *in_reqs,
+                                   const char *type)
 {
        int r;
-       struct zd_ioreq32 reqs[2] = {
-               [0] = { .addr = CR_MAC_ADDR_P1 },
-               [1] = { .addr = CR_MAC_ADDR_P2 },
-       };
+       struct zd_ioreq32 reqs[2] = {in_reqs[0], in_reqs[1]};
 
        if (mac_addr) {
                reqs[0].value = (mac_addr[3] << 24)
@@ -388,9 +384,9 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
                              |  mac_addr[0];
                reqs[1].value = (mac_addr[5] <<  8)
                              |  mac_addr[4];
-               dev_dbg_f(zd_chip_dev(chip), "mac addr %pM\n", mac_addr);
+               dev_dbg_f(zd_chip_dev(chip), "%s addr %pM\n", type, mac_addr);
        } else {
-               dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n");
+               dev_dbg_f(zd_chip_dev(chip), "set NULL %s\n", type);
        }
 
        mutex_lock(&chip->mutex);
@@ -399,6 +395,29 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
        return r;
 }
 
+/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
+ *              CR_MAC_ADDR_P2 must be overwritten
+ */
+int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+{
+       static const struct zd_ioreq32 reqs[2] = {
+               [0] = { .addr = CR_MAC_ADDR_P1 },
+               [1] = { .addr = CR_MAC_ADDR_P2 },
+       };
+
+       return zd_write_mac_addr_common(chip, mac_addr, reqs, "mac");
+}
+
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
+{
+       static const struct zd_ioreq32 reqs[2] = {
+               [0] = { .addr = CR_BSSID_P1 },
+               [1] = { .addr = CR_BSSID_P2 },
+       };
+
+       return zd_write_mac_addr_common(chip, bssid, reqs, "bssid");
+}
+
 int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
 {
        int r;
index f8bbf7d302ae6758b3d98ea69acf3dbeb4ad41e2..7b0c58ce705602c3eda52051a19eff1828ab8586 100644 (file)
@@ -881,6 +881,7 @@ static inline u8 _zd_chip_get_channel(struct zd_chip *chip)
 u8  zd_chip_get_channel(struct zd_chip *chip);
 int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
 int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid);
 int zd_chip_switch_radio_on(struct zd_chip *chip);
 int zd_chip_switch_radio_off(struct zd_chip *chip);
 int zd_chip_enable_int(struct zd_chip *chip);
index 487ed33e951d668c26f2bf58ad93c577c458765b..ab0d1b9a08ec67094a2da1bb58d5a77758c446e9 100644 (file)
@@ -231,6 +231,26 @@ static int set_rx_filter(struct zd_mac *mac)
        return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
 }
 
+static int set_mac_and_bssid(struct zd_mac *mac)
+{
+       int r;
+
+       if (!mac->vif)
+               return -1;
+
+       r = zd_write_mac_addr(&mac->chip, mac->vif->addr);
+       if (r)
+               return r;
+
+       /* Vendor driver after setting MAC either sets BSSID for AP or
+        * filter for other modes.
+        */
+       if (mac->type != NL80211_IFTYPE_AP)
+               return set_rx_filter(mac);
+       else
+               return zd_write_bssid(&mac->chip, mac->vif->addr);
+}
+
 static int set_mc_hash(struct zd_mac *mac)
 {
        struct zd_mc_hash hash;
@@ -888,7 +908,9 @@ static int zd_op_add_interface(struct ieee80211_hw *hw,
                return -EOPNOTSUPP;
        }
 
-       return zd_write_mac_addr(&mac->chip, vif->addr);
+       mac->vif = vif;
+
+       return set_mac_and_bssid(mac);
 }
 
 static void zd_op_remove_interface(struct ieee80211_hw *hw,
@@ -896,6 +918,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_write_mac_addr(&mac->chip, NULL);
 }
index ff7ef30372a14dc8319979ee93e263446b11dcca..0ec6bde0b37c8aa5cb50fe3f29412481d651e378 100644 (file)
@@ -172,6 +172,7 @@ struct zd_mac {
        spinlock_t lock;
        spinlock_t intr_lock;
        struct ieee80211_hw *hw;
+       struct ieee80211_vif *vif;
        struct housekeeping housekeeping;
        struct work_struct set_rts_cts_work;
        struct work_struct process_intr;