2010-02-14 23:35:09

by Benoit Papillault

[permalink] [raw]
Subject: [PATCH 1/2] zd1211rw: Experimental change to add proper monitor support

Without this patch, monitor mode does not returns all frames. With this patch,
the performance are quite poor if we create a monitor interface. Note :
creating a monitor interface with the "cook" flag has no impact on performance.

Signed-off-by: Benoit Papillault <[email protected]>
---
drivers/net/wireless/zd1211rw/zd_mac.c | 20 +++++++++++++++++++-
1 files changed, 19 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 2d555cc..9cb6cbc 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -904,8 +904,26 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct zd_mac *mac = zd_hw_mac(hw);
struct ieee80211_conf *conf = &hw->conf;
+ int ret;

- return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+ /*
+ * Warning : enabling this register kills RX & TX
+ * performance
+ */
+ u32 cr_sniffer = !!(conf->flags & IEEE80211_CONF_MONITOR);
+ ret = zd_iowrite32(&mac->chip, CR_SNIFFER_ON, cr_sniffer);
+ if (!ret)
+ return ret;
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ ret = zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
+ if (!ret)
+ return ret;
+ }
+
+ return 0;
}

static void zd_process_intr(struct work_struct *work)
--
1.5.6.5



2010-02-15 07:33:21

by Benoit Papillault

[permalink] [raw]
Subject: [PATCH v2] zd1211rw: Set hardware BSSID and set hardware IBSS mode

Both changes allow for proper TSF synchronisation in STA and IBSS mode.

v2: Fix error handling logic

Signed-off-by: Benoit Papillault <[email protected]>
---
drivers/net/wireless/zd1211rw/zd_chip.c | 21 ++++++++++++++++++++-
drivers/net/wireless/zd1211rw/zd_chip.h | 1 +
drivers/net/wireless/zd1211rw/zd_mac.c | 8 +++++---
3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 7ca95c4..f525459 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -397,6 +397,25 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
return r;
}

+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
+{
+ struct zd_ioreq32 ioreqs[] = {
+ { CR_BSSID_P1, 0 },
+ { CR_BSSID_P2, 0 }
+ };
+
+ if (bssid) {
+ ioreqs[0].value = (bssid[3] << 24)
+ | (bssid[2] << 16)
+ | (bssid[1] << 8)
+ | bssid[0];
+ ioreqs[1].value = (bssid[5] << 8)
+ | bssid[4];
+ }
+
+ return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
{
int r;
@@ -806,7 +825,7 @@ static int hw_init_hmac(struct zd_chip *chip)
{ CR_AFTER_PNP, 0x1 },
{ CR_WEP_PROTECT, 0x114 },
{ CR_IFS_VALUE, IFS_VALUE_DEFAULT },
- { CR_CAM_MODE, MODE_AP_WDS},
+ { CR_CAM_MODE, MODE_IBSS},
};

ZD_ASSERT(mutex_is_locked(&chip->mutex));
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index f8bbf7d..7b0c58c 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -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);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 9cb6cbc..0de176b 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -913,13 +913,13 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
*/
u32 cr_sniffer = !!(conf->flags & IEEE80211_CONF_MONITOR);
ret = zd_iowrite32(&mac->chip, CR_SNIFFER_ON, cr_sniffer);
- if (!ret)
+ if (ret)
return ret;
}

if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
ret = zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
- if (!ret)
+ if (ret)
return ret;
}

@@ -1096,7 +1096,9 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
mac->associated = associated;
spin_unlock_irq(&mac->lock);

- /* TODO: do hardware bssid filtering */
+ if (changes & BSS_CHANGED_BSSID) {
+ zd_write_bssid(&mac->chip, bss_conf->bssid);
+ }

if (changes & BSS_CHANGED_ERP_PREAMBLE) {
spin_lock_irqsave(&mac->lock, flags);
--
1.5.6.5


2010-02-15 00:29:09

by Gábor Stefanik

[permalink] [raw]
Subject: Re: [PATCH 1/2] zd1211rw: Experimental change to add proper monitor support

On Mon, Feb 15, 2010 at 12:34 AM, Benoit Papillault
<[email protected]> wrote:
> Without this patch, monitor mode does not returns all frames. With this patch,
> the performance are quite poor if we create a monitor interface. Note :
> creating a monitor interface with the "cook" flag has no impact on performance.
>
> Signed-off-by: Benoit Papillault <[email protected]>
> ---
> ?drivers/net/wireless/zd1211rw/zd_mac.c | ? 20 +++++++++++++++++++-
> ?1 files changed, 19 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
> index 2d555cc..9cb6cbc 100644
> --- a/drivers/net/wireless/zd1211rw/zd_mac.c
> +++ b/drivers/net/wireless/zd1211rw/zd_mac.c
> @@ -904,8 +904,26 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
> ?{
> ? ? ? ?struct zd_mac *mac = zd_hw_mac(hw);
> ? ? ? ?struct ieee80211_conf *conf = &hw->conf;
> + ? ? ? int ret;
>
> - ? ? ? return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
> + ? ? ? if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
> + ? ? ? ? ? ? ? /*
> + ? ? ? ? ? ? ? ?* Warning : enabling this register kills RX & TX
> + ? ? ? ? ? ? ? ?* performance
> + ? ? ? ? ? ? ? ?*/
> + ? ? ? ? ? ? ? u32 cr_sniffer = !!(conf->flags & IEEE80211_CONF_MONITOR);
> + ? ? ? ? ? ? ? ret = zd_iowrite32(&mac->chip, CR_SNIFFER_ON, cr_sniffer);
> + ? ? ? ? ? ? ? if (!ret)
> + ? ? ? ? ? ? ? ? ? ? ? return ret;

Your logic is the wrong way around. You should return if nonzero, not if zero.

> + ? ? ? }
> +
> + ? ? ? if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
> + ? ? ? ? ? ? ? ret = zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
> + ? ? ? ? ? ? ? if (!ret)
> + ? ? ? ? ? ? ? ? ? ? ? return ret;
> + ? ? ? }
> +
> + ? ? ? return 0;
> ?}
>
> ?static void zd_process_intr(struct work_struct *work)
> --
> 1.5.6.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>



--
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)

2010-02-15 07:31:34

by Benoit Papillault

[permalink] [raw]
Subject: Re: [zd1211-devs] [PATCH 1/2] zd1211rw: Experimental change to add proper monitor support

G?bor Stefanik a ?crit :
> On Mon, Feb 15, 2010 at 12:34 AM, Benoit Papillault
> <[email protected]> wrote:
>
>> Without this patch, monitor mode does not returns all frames. With this patch,
>> the performance are quite poor if we create a monitor interface. Note :
>> creating a monitor interface with the "cook" flag has no impact on performance.
>>
>> Signed-off-by: Benoit Papillault <[email protected]>
>> ---
>> drivers/net/wireless/zd1211rw/zd_mac.c | 20 +++++++++++++++++++-
>> 1 files changed, 19 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
>> index 2d555cc..9cb6cbc 100644
>> --- a/drivers/net/wireless/zd1211rw/zd_mac.c
>> +++ b/drivers/net/wireless/zd1211rw/zd_mac.c
>> @@ -904,8 +904,26 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
>> {
>> struct zd_mac *mac = zd_hw_mac(hw);
>> struct ieee80211_conf *conf = &hw->conf;
>> + int ret;
>>
>> - return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
>> + if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
>> + /*
>> + * Warning : enabling this register kills RX & TX
>> + * performance
>> + */
>> + u32 cr_sniffer = !!(conf->flags & IEEE80211_CONF_MONITOR);
>> + ret = zd_iowrite32(&mac->chip, CR_SNIFFER_ON, cr_sniffer);
>> + if (!ret)
>> + return ret;
>>
>
> Your logic is the wrong way around. You should return if nonzero, not if zero.
>
>
>> + }
>> +
>> + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
>> + ret = zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
>> + if (!ret)
>> + return ret;
>> + }
>> +
>> + return 0;
>> }
>>
>> static void zd_process_intr(struct work_struct *work)
>> --
>> 1.5.6.5
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
>> the body of a message to [email protected]
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>>
>
>
>
>
You are right. I will resend a patch.

Regards,
Benoit


2010-02-15 22:26:57

by Benoit Papillault

[permalink] [raw]
Subject: Re: [PATCH v2] zd1211rw: Set hardware BSSID and set hardware IBSS mode

G?bor Stefanik a ?crit :
> On Mon, Feb 15, 2010 at 8:33 AM, Benoit Papillault
> <[email protected]> wrote:
>
>> Both changes allow for proper TSF synchronisation in STA and IBSS mode.
>>
>> v2: Fix error handling logic
>>
>> Signed-off-by: Benoit Papillault <[email protected]>
>> ---
>> drivers/net/wireless/zd1211rw/zd_chip.c | 21 ++++++++++++++++++++-
>> drivers/net/wireless/zd1211rw/zd_chip.h | 1 +
>> drivers/net/wireless/zd1211rw/zd_mac.c | 8 +++++---
>> 3 files changed, 26 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
>> index 7ca95c4..f525459 100644
>> --- a/drivers/net/wireless/zd1211rw/zd_chip.c
>> +++ b/drivers/net/wireless/zd1211rw/zd_chip.c
>> @@ -397,6 +397,25 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
>> return r;
>> }
>>
>> +int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
>> +{
>> + struct zd_ioreq32 ioreqs[] = {
>> + { CR_BSSID_P1, 0 },
>> + { CR_BSSID_P2, 0 }
>> + };
>> +
>> + if (bssid) {
>> + ioreqs[0].value = (bssid[3] << 24)
>> + | (bssid[2] << 16)
>> + | (bssid[1] << 8)
>> + | bssid[0];
>> + ioreqs[1].value = (bssid[5] << 8)
>> + | bssid[4];
>> + }
>> +
>> + return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
>> +}
>> +
>> int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
>> {
>> int r;
>> @@ -806,7 +825,7 @@ static int hw_init_hmac(struct zd_chip *chip)
>> { CR_AFTER_PNP, 0x1 },
>> { CR_WEP_PROTECT, 0x114 },
>> { CR_IFS_VALUE, IFS_VALUE_DEFAULT },
>> - { CR_CAM_MODE, MODE_AP_WDS},
>> + { CR_CAM_MODE, MODE_IBSS},
>> };
>>
>> ZD_ASSERT(mutex_is_locked(&chip->mutex));
>> diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
>> index f8bbf7d..7b0c58c 100644
>> --- a/drivers/net/wireless/zd1211rw/zd_chip.h
>> +++ b/drivers/net/wireless/zd1211rw/zd_chip.h
>> @@ -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);
>> diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
>> index 9cb6cbc..0de176b 100644
>> --- a/drivers/net/wireless/zd1211rw/zd_mac.c
>> +++ b/drivers/net/wireless/zd1211rw/zd_mac.c
>> @@ -913,13 +913,13 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
>> */
>> u32 cr_sniffer = !!(conf->flags & IEEE80211_CONF_MONITOR);
>> ret = zd_iowrite32(&mac->chip, CR_SNIFFER_ON, cr_sniffer);
>> - if (!ret)
>> + if (ret)
>> return ret;
>> }
>>
>
>
> Crosstalk from your other patch?
>
>
Oops .. I did something wrong with git rebase I guess. Will resent.

Regards,
Benoit


2010-02-15 11:44:21

by Gábor Stefanik

[permalink] [raw]
Subject: Re: [PATCH v2] zd1211rw: Set hardware BSSID and set hardware IBSS mode

On Mon, Feb 15, 2010 at 8:33 AM, Benoit Papillault
<[email protected]> wrote:
> Both changes allow for proper TSF synchronisation in STA and IBSS mode.
>
> v2: Fix error handling logic
>
> Signed-off-by: Benoit Papillault <[email protected]>
> ---
> ?drivers/net/wireless/zd1211rw/zd_chip.c | ? 21 ++++++++++++++++++++-
> ?drivers/net/wireless/zd1211rw/zd_chip.h | ? ?1 +
> ?drivers/net/wireless/zd1211rw/zd_mac.c ?| ? ?8 +++++---
> ?3 files changed, 26 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
> index 7ca95c4..f525459 100644
> --- a/drivers/net/wireless/zd1211rw/zd_chip.c
> +++ b/drivers/net/wireless/zd1211rw/zd_chip.c
> @@ -397,6 +397,25 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
> ? ? ? ?return r;
> ?}
>
> +int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
> +{
> + ? ? ? struct zd_ioreq32 ioreqs[] = {
> + ? ? ? ? ? ? ? { CR_BSSID_P1, 0 },
> + ? ? ? ? ? ? ? { CR_BSSID_P2, 0 }
> + ? ? ? };
> +
> + ? ? ? if (bssid) {
> + ? ? ? ? ? ? ? ioreqs[0].value = (bssid[3] << 24)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | (bssid[2] << 16)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | (bssid[1] << ?8)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ?bssid[0];
> + ? ? ? ? ? ? ? ioreqs[1].value = (bssid[5] << ?8)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ?bssid[4];
> + ? ? ? }
> +
> + ? ? ? return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
> +}
> +
> ?int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
> ?{
> ? ? ? ?int r;
> @@ -806,7 +825,7 @@ static int hw_init_hmac(struct zd_chip *chip)
> ? ? ? ? ? ? ? ?{ CR_AFTER_PNP, ? ? ? ? ? ? ? ? 0x1 },
> ? ? ? ? ? ? ? ?{ CR_WEP_PROTECT, ? ? ? ? ? ? ? 0x114 },
> ? ? ? ? ? ? ? ?{ CR_IFS_VALUE, ? ? ? ? ? ? ? ? IFS_VALUE_DEFAULT },
> - ? ? ? ? ? ? ? { CR_CAM_MODE, ? ? ? ? ? ? ? ? ?MODE_AP_WDS},
> + ? ? ? ? ? ? ? { CR_CAM_MODE, ? ? ? ? ? ? ? ? ?MODE_IBSS},
> ? ? ? ?};
>
> ? ? ? ?ZD_ASSERT(mutex_is_locked(&chip->mutex));
> diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
> index f8bbf7d..7b0c58c 100644
> --- a/drivers/net/wireless/zd1211rw/zd_chip.h
> +++ b/drivers/net/wireless/zd1211rw/zd_chip.h
> @@ -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);
> diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
> index 9cb6cbc..0de176b 100644
> --- a/drivers/net/wireless/zd1211rw/zd_mac.c
> +++ b/drivers/net/wireless/zd1211rw/zd_mac.c
> @@ -913,13 +913,13 @@ static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
> ? ? ? ? ? ? ? ? */
> ? ? ? ? ? ? ? ?u32 cr_sniffer = !!(conf->flags & IEEE80211_CONF_MONITOR);
> ? ? ? ? ? ? ? ?ret = zd_iowrite32(&mac->chip, CR_SNIFFER_ON, cr_sniffer);
> - ? ? ? ? ? ? ? if (!ret)
> + ? ? ? ? ? ? ? if (ret)
> ? ? ? ? ? ? ? ? ? ? ? ?return ret;
> ? ? ? ?}


Crosstalk from your other patch?

>
> ? ? ? ?if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
> ? ? ? ? ? ? ? ?ret = zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
> - ? ? ? ? ? ? ? if (!ret)
> + ? ? ? ? ? ? ? if (ret)
> ? ? ? ? ? ? ? ? ? ? ? ?return ret;
> ? ? ? ?}
>
> @@ -1096,7 +1096,9 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
> ? ? ? ?mac->associated = associated;
> ? ? ? ?spin_unlock_irq(&mac->lock);
>
> - ? ? ? /* TODO: do hardware bssid filtering */
> + ? ? ? if (changes & BSS_CHANGED_BSSID) {
> + ? ? ? ? ? ? ? zd_write_bssid(&mac->chip, bss_conf->bssid);
> + ? ? ? }
>
> ? ? ? ?if (changes & BSS_CHANGED_ERP_PREAMBLE) {
> ? ? ? ? ? ? ? ?spin_lock_irqsave(&mac->lock, flags);
> --
> 1.5.6.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
>



--
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)

2010-02-14 23:35:14

by Benoit Papillault

[permalink] [raw]
Subject: [PATCH 2/2] zd1211rw: Set hardware BSSID and set hardware IBSS mode

Both changes allow for proper TSF synchronisation in STA and IBSS mode.

Signed-off-by: Benoit Papillault <[email protected]>
---
drivers/net/wireless/zd1211rw/zd_chip.c | 21 ++++++++++++++++++++-
drivers/net/wireless/zd1211rw/zd_chip.h | 1 +
drivers/net/wireless/zd1211rw/zd_mac.c | 4 +++-
3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 7ca95c4..f525459 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -397,6 +397,25 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
return r;
}

+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
+{
+ struct zd_ioreq32 ioreqs[] = {
+ { CR_BSSID_P1, 0 },
+ { CR_BSSID_P2, 0 }
+ };
+
+ if (bssid) {
+ ioreqs[0].value = (bssid[3] << 24)
+ | (bssid[2] << 16)
+ | (bssid[1] << 8)
+ | bssid[0];
+ ioreqs[1].value = (bssid[5] << 8)
+ | bssid[4];
+ }
+
+ return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs));
+}
+
int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
{
int r;
@@ -806,7 +825,7 @@ static int hw_init_hmac(struct zd_chip *chip)
{ CR_AFTER_PNP, 0x1 },
{ CR_WEP_PROTECT, 0x114 },
{ CR_IFS_VALUE, IFS_VALUE_DEFAULT },
- { CR_CAM_MODE, MODE_AP_WDS},
+ { CR_CAM_MODE, MODE_IBSS},
};

ZD_ASSERT(mutex_is_locked(&chip->mutex));
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index f8bbf7d..7b0c58c 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -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);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 9cb6cbc..2559da5 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -1096,7 +1096,9 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
mac->associated = associated;
spin_unlock_irq(&mac->lock);

- /* TODO: do hardware bssid filtering */
+ if (changes & BSS_CHANGED_BSSID) {
+ zd_write_bssid(&mac->chip, bss_conf->bssid);
+ }

if (changes & BSS_CHANGED_ERP_PREAMBLE) {
spin_lock_irqsave(&mac->lock, flags);
--
1.5.6.5